使用Redis位图的高效分析库
项目描述
全新! 尝试我们全新的独立 bitmapist-server,它将内存效率提高了443倍,使您的设置更加经济且可扩展。它与运行在Redis上的bitmapist完全兼容。
bitmapist:用于Redis的强大分析库
此Python库使得实现能够回答以下问题的实时、高度可扩展的分析成为可能
- 用户123今天是否在线?本周?这个月?
- 用户123是否执行了动作“X”?
- 这个月有多少用户是活跃的?这个小时有多少用户是活跃的?
- 这个星期有多少唯一用户执行了动作“X”?
- 上周活跃的用户中有多少百分比的用户仍然活跃?
- 上个月活跃的用户中,有多少百分比的用户这个月仍然活跃?
- 哪些用户执行了操作“X”?
这个库非常容易使用,并允许您轻松地创建自己的报告。
使用Redis位图,您可以在非常小的内存量(兆字节)中存储数百万用户的活动事件。您在使用大ID时应小心,因为这可能需要更多的内存。ID应在范围[0, 2^32)内。
此外,bitmapist可以生成以下协群图
- 用户留存协群
- 在过去[天数、周数、月数]中活跃的用户中有多少百分比的用户仍然活跃?
- 执行了操作X的用户中有多少百分比也执行了操作Y(并且随着时间的推移)
- 还有很多其他事情!
如果您想了解更多关于位图的信息,请阅读以下内容
- http://blog.getspool.com/2011/11/29/fast-easy-realtime-metrics-using-redis-bitmaps/
- https://redis.ac.cn/commands/setbit
- http://en.wikipedia.org/wiki/Bit_array
- http://www.slideshare.net/crashlytics/crashlytics-on-redis-analytics
安装
可以通过以下方式非常容易地安装
$ pip install bitmapist4
端口
示例
设置东西
import bitmapist4
b = bitmapist4.Bitmapist()
将用户123标记为活跃且已播放歌曲
b.mark_event('active', 123)
b.mark_event('song:played', 123)
回答用户123这个月是否活跃
assert 123 in b.MonthEvents('active')
assert 123 in b.MonthEvents('song:played')
有多少用户本周活跃?
len(b.WeekEvents('active'))
遍历本周所有活跃的用户
for uid in b.WeekEvents('active'):
print(uid)
要探索任何特定的一天、一周、一个月或一年而不是当前日期,您可以使用带有from_date
静态方法的任何日期时间对象创建事件。
specific_date = datetime.datetime(2018, 1, 1)
ev = b.MonthEvents('active').from_date(specific_date)
print(len(ev))
有prev
和next
方法返回“兄弟”事件,允许您在不使用复杂迭代器的情况下遍历事件。一个delta
方法允许您向前或向后跳转多个步骤。统一的API允许您使用所有类型的基事件(从小时到年)使用相同的代码。
current_month = b.MonthEvents('active')
prev_month = current_month.prev()
next_month = current_month.next()
year_ago = current_month.delta(-12)
每个事件对象都有period_start
和period_end
方法来查找事件的时间范围。当不希望缓存“未来事件”时,这可能很有用。
ev = b.MonthEvent('active', dt)
if ev.period_end() < datetime.datetime.utcnow():
cache.set('active_users_<...>', len(ev))
按小时跟踪被禁用(为了节省内存!)您可以使用构造函数参数启用它。
b = bitmapist4.Bitmapist(track_hourly=True)
您还可以向mark_event
提供一个额外的参数来绕过默认值:
b.mark_event('active', 123, track_hourly=False)
唯一事件
有时事件的数据没有多少意义,您更感兴趣的是用户在其一生中是否至少发生了一次该特定事件。
有一个UniqueEvents
模型用于此目的。该模型只创建一个Redis密钥,不依赖于日期。
您可以结合唯一事件和其他类型的事件。
A/B测试示例
active = b.DailyEvents('active')
a = b.UniqueEvents('signup_form:classic')
b = b.UniqueEvents('signup_form:new')
print("Active users, signed up with classic form", len(active & a))
print("Active users, signed up with new form", len(active & b))
您可以使用b.mark_unique
标记这些用户,或者您可以为所有标记的密钥自动填充额外的唯一协群
b = bitmapist4.Bitmapist(track_unique=True)
b.mark_event('premium', 1)
assert 1 in b.UniqueEvents('premium')
执行位操作
上个月活跃的用户中有多少百分比的用户这个月仍然活跃?
ev = b.MonthEvents('active')
active_2months = ev & ev.prev()
print(len(active_2months))
# Is 123 active for 2 months?
assert 123 in active_2months
支持运算符&
、|
、^
和~
。
这适用于嵌套位操作(想象一下您能做什么;-))!
删除事件
如果您想要永久删除任何时间段的标记事件,您可以使用delete()
方法
ev = b.MonthEvents.from_date('active', last_month)
ev.delete()
如果您想要删除所有bitmapist事件,请使用
b.delete_all_events()
位操作的结果默认情况下被缓存。对于包含未完成的周期的操作,它们被缓存60秒,对于其他情况,它们被缓存24小时。
您可能需要显式重置缓存
ev = b.MonthEvents('active')
active_2months = ev & ev.prev()
# Delete the temporary AND operation
active_2months.delete()
# delete all bit operations (slow if you have many millions of keys in Redis)
b.delete_temporary_bitop_keys()
使用事务进行批量更新
如果您经常同时执行多个更新,您可以从Redis管道中受益,它被bitmapist内部的交易包装。
with b.transaction():
b.mark_event('active')
b.mark_event('song:played')
从先前版本迁移
“bitmapist4.Bitmapist”实例的API与之前版本的bitmapist(模块级)API基本兼容。以下列出了一些显著的变更。
- 移除了用于选择服务器的“system”属性。您应使用不同的Bitmapist类实例代替。如果您使用“system”与管道一起工作,则应切换到事务。
- bitmapist.TRACK_HOURLY和bitmapist.TRACK_UNIQUE模块级常量已移动到bitmapist4.Bitmapist属性中,并可以通过类构造函数进行设置。
- 在数据库层面,新的bitmapist4使用“bitmapist_”作为Redis键的前缀,而旧的bitmapist由于历史原因使用“trackist_”。如果您想继续使用旧数据库,或者想使用bitmapist和bitmapist4对同一数据库进行操作,您需要显式地将键前缀设置为“trackist_”。
- 如果您使用bitmapist-server,请确保您使用的是1.2版本或更高版本。此版本增加了对EXPIRE命令的支持,该命令用于使临时bitop键过期。
替换以下可能的老旧代码
import bitmapist
bitmapist.setup_redis('default', 'localhost', 6380)
...
bitmapist.mark_event('acive', user_id)
为以下类似的代码
from bitmapist4 import Bitmapist
bitmapist = Bitmapist('redis://localhost:6380', key_prefix='trackist_')
...
bitmapist.mark_event('acive', user_id)
Bitmapist群体
群体是一组具有共同特征的主体(通常是那些在选定时间段内经历共同事件的主体,如出生或毕业)。
您可以使用bitmapist4.cohort.get_cohort_table()
函数获取群体表。
该表的每一行都回答了“在给定时间内,群体中的哪部分主体执行了活动”的问题,而该行的第N个单元格表示在活动后N天(或周,或月)仍执行该活动的用户数量(绝对值或百分比)。
群体表的每一列都展开不同类似群体随时间的行为。最新的一行显示传入的群体参数的行为,上面的一行显示相似群体的行为,但时间向前推移1天(或周,或月),依此类推。
例如,考虑以下群体统计数据
table = get_cohort_table(b.WeekEvents('registered'), b.WeekEvents('active'))
此表显示了注册用户在注册后同一周、一周后、两周后等仍活跃的比率。
默认情况下,该表显示20行。
第一行表示20周前注册的用户群体的统计数据。第二行表示19周前注册的相同统计数据,以此类推,直到最新的一行显示本周注册的用户。自然地,最后一行将只包含一个单元格,该单元格包含本周注册并且本周也活跃的用户数量。
然后您可以将其渲染为HTML,或使用df()方法导出为Pandas数据框。
来自http://www.gharchive.org/的用户活动样本
In [1]: from bitmapist4 import Bitmapist, cohort
In [2]: b = Bitmapist()
In [3]: cohort.get_cohort_table(b.WeekEvents('active'), b.WeekEvents('active'), rows=5, use_percent=False).df()
Out[3]:
cohort 0 1 2 3 4
05 Nov 2018 137420 137420 25480.0 18358.0 21575.0 18430.0
12 Nov 2018 150975 150975 22195.0 25833.0 21165.0 NaN
19 Nov 2018 121417 121417 22477.0 15796.0 NaN NaN
26 Nov 2018 152027 152027 25606.0 NaN NaN NaN
03 Dec 2018 130470 130470 NaN NaN NaN NaN
可以使用stylize()方法进一步对数据框进行着色(以便在Jupyter笔记本中显示)。
版权:2012-2018由Doist Ltd.所有
许可证:BSD
项目详情
下载文件
下载适合您平台的应用程序。如果您不确定选择哪个,请了解有关安装包的更多信息。