你们有没有想过如何统计活跃用户数量?若是是本身作,那该怎么作?git
这里思考一分钟,后面我将分享一下如何使用 redis 中的位图来统计活跃用户数。github
位图(bitmap) 是二进制的 byte 数组,也能够简单理解成是一个普通字符串。它将二进制数据存储在 byte 数组中以达到存储数据的做用。redis
图 1.1数组
在解释什么是位图的时候说过,位图能够理解成是一个普通字符串,那么咱们为何要用位图而不是字符串呢 ?markdown
下面是在 redis 中存储字符串的一个示意图oop
图 2.1spa
如图,存储字符串是将字符串二进制数组的形式存储在 redis 中,位图能够直接对 二进制的数组操做,位图的优点在于能够用 0 和 1来存储布尔值,这大大下降了咱们的存储空间消耗。因为这个特性,咱们用位图来记录签到信息,记录活跃用户等,能够达到节省空间的能力(后面会有介绍)。code
那咱们如何对二进制的数组进行操做呢?orm
setbit | getbit对象
上文说的二进制数组咱们能够对它作添加、查找及修改的功能
如何进行添加和查找呢?
setbit [keyName] [offset] [value]
复制代码
offset:偏移量,指的是数组的下标; value: 数据, 只能是 0 和 1。
这条命令既能够添加数据也能够修改数据。
如何进行查找呢 ?
getbit [keyName] [offset]
复制代码
offset:偏移量,指的是数组的下标。这里,除了设置 value 为 1 的 offset, 查询其余的都返回 0
补充:上面说了位图能够理解成字符串,那么它们之间能够互相操做吗?
图 2.2
请对照上图,咱们一块儿完成下面的探究:以字符串存储,能够经过 getbit
命令获取到值吗?
咱们能够结合查询和图片所示的 offset 及所对应的值来验证
> set str hi
OK
> getbit str 0
(integer) 0
> getbit str 4
(integer) 1
> getbit str 7
(integer) 0
> getbit str 15
(integer) 1
复制代码
结论:能够的
以字符串存储,能够经过 settbit
修改值吗?
咱们能够试着将 offset 7 对应的 value 改为 1, 若是成功了,h 字符应该变成 i
> setbit str 7 1
(integer) 0
> get str
"ii"
复制代码
结论:能够
用 setbit
存储字符串的二进制数据,能够经过 get
获取字符串吗?
咱们将 字符 h 的二进制存入位图,看能够能经过 get 获取
> setbit bitmap 0 0
(integer) 0
> setbit bitmap 1 1
(integer) 0
> setbit bitmap 2 1
(integer) 0
> setbit bitmap 3 0
(integer) 0
> setbit bitmap 4 1
(integer) 0
> setbit bitmap 5 0
(integer) 0
> setbit bitmap 6 0
(integer) 0
> setbit bitmap 7 0
(integer) 0
> get bitmap
"h"
复制代码
结论:能够
上面介绍了位图的基本概念和使用,经过一系列的探究但愿能帮助你们更好的理解位图
那么,如何将位图应用的项目中呢?
bitcount | bitpos
bitcount
是用来查找 1 出现的次数,既能够对位图使用也能够对字符串使用,用法以下:
bitcount [keyName] [startWith] [endWith]
复制代码
注意:这里的 startWith 和 endWith 不是二进制数组的下标(offset)
这里的 startWith 和 endWith 能够理解成是字符串的下标,一个字符串对应 8 位二进制数据;它们至关因而截取字符串,如 s= "hi"
, s[0:0] = "h"
, 它所对应的二进制数组的下标是 0,7,以此类推。
其实这里很差解释,先来带代码,能够结合着上面的 图 2.2 看一下,你们后面能够在领悟一下
> set str hi
> bitcount str 0 0
(integer) 4
> bitcount str 0 1
(integer) 8
> bitcount str
(integer) 8
复制代码
注意:startWith 和 endWith 不设置的时候默认所有范围
应用场景:统计活跃用户的数量
bitpos
用来查找指定范围内出现的第一个 0 或 1,用法以下:
bitpos [keyName] [bit] [start] [end]
复制代码
bit: 要找的 0 或者 1, start 和 end 同上面的 startWith 和 endWith
应用场景:获取第一次签到和第一次未签到的时间
上面大体说了 2 个应用场景:
我在这里稍微介绍一下思路,而后附上一个 统计活跃用户的数量 可供参考
统计活跃用户的数量
login:2020-3
offset
, 如 id
对应二进制数组的下标,id
为 int
setbit
将对应的offset
设置成 1bitcount
统计某个行为和时间范围的活跃人数,如 bitcount login:2020-3
Demo: DailyActiveUsers
获取第一次签到和第一次未签到的时间
login:2020-3:Tom
offset
, 如 1号对应二进制数组的下标 0, 2 号为 1setbit
将对应的offset
设置成 1bitpos
统计某个行为和时间范围和对象的签到状况,如 bitpos login:2020-3:Tom 1
上述内容对你们有所帮助的话,请帮我 点个赞👍,创做不易,感谢支持!
若是本文有任何错误,感谢各位批评指教 !