Redis提供的Bitmaps这个“数据结构”可以实现对位的操作。Bitmaps本身不是一种数据结构,实际上就是字符串,但是它可以对字符串的位进行操作。
可以把Bitmaps想象成一个以位为单位数组,数组中的每个单元只能存0或者1,数组的下标在bitmaps中叫做偏移量。单个bitmaps的最大长度是512MB,即2^32个比特位。
命令:setbit key offset value
例如:setbit unique:users:2017-07-11 0 1 代表2017-07-11这天的独立访问用户的Bitmaps,用下标代表用户ID,1表示访问,0表示未访问,则上述命令代表第一个用户2017-07-11这天访问了系统。
命令:getbit key offset
例如: setbit unique:users:2017-07-11 0 1
getbit unique:users:2017-07-11 0
返回: 1
假如offset=0的元素不存在,则返回结果0
命令:bitcount key [start] [end]
例如:setbit unique:users:2017-07-11 0 1
setbit unique:users:2017-07-11 9 1
bitcount unique:users:2017-07-11
返回: 2
bitcount unique:users:2017-07-11 0 0
返回:1
2.4.1 bitop and destkey key[key…] 计算Bitmaps的交集的数量
命令:bitop and destkey key[key…]
返回:保存到 destkey 的字符串(1字符等于8位)的长度,和输入 key 中最长的字符串长度相等。
例如:
redis> SETBIT bits-1 0 1 # bits-1 = 1001
(integer) 0
redis> SETBIT bits-1 3 1
(integer) 0
redis> SETBIT bits-2 0 1 # bits-2 = 1101
(integer) 0
redis> SETBIT bits-2 1 1
(integer) 0
redis> SETBIT bits-2 3 1
(integer) 0
redis> BITOP AND and-result bits-1bits-2
(integer) 1
redis> GETBIT and-result 0 # and-result = 1001
(integer) 1
redis> GETBIT and-result 1
(integer) 0
redis> GETBIT and-result 2
(integer) 0
redis> GETBIT and-result 3
(integer) 1
2.4.2 bitop or destkey key[key…] 计算Bitmaps的并集的数量
命令:bitop or destkey key[key…]
返回:保存到 destkey 的字符串(1字符等于8位)的长度,和输入 key 中最长的字符串长度相等。
例如:
redis> SETBIT bits-1 0 1 # bits-1 = 1001
(integer) 0
redis> SETBIT bits-1 3 1
(integer) 0
redis> SETBIT bits-2 0 1 # bits-2 = 1101
(integer) 0
redis> SETBIT bits-2 1 1
(integer) 0
redis> SETBIT bits-2 3 1
(integer) 0
redis> BITOP or or-result bits-1 bits-2
(integer) 1
redis> GETBIT or-result 0 # or-result = 1101
(integer) 1
redis> GETBIT or -result 1
(integer) 1
redis> GETBIT or -result 2
(integer) 0
redis> GETBIT or -result 3
(integer) 1
2.4.3 bitop not destkey key 计算Bitmaps的非集的数量
命令:bitop not destkey key
返回:保存到 destkey 的字符串(1字符等于8位)的长度,和输入 key 中最长的字符串长度相等。
例如:
redis> SETBIT bits-1 0 1 # bits-1 = 1001
(integer) 0
redis> SETBIT bits-1 3 1
(integer) 0
redis> SETBIT bits-2 3 1
(integer) 0
redis> BITOP not not-result bits-1
(integer) 1
redis> GETBIT not -result 0 # and-result = 0110
(integer) 0
redis> GETBIT not -result 1
(integer) 1
redis> GETBIT not -result 2
(integer) 1
redis> GETBIT not -result 3
(integer) 0
2.4.4 bitop xor destkey key 计算Bitmaps的异或集的数量
命令:bitop xor destkey key[key..]
返回:保存到 destkey 的字符串(1字符等于8位)的长度,和输入 key 中最长的字符串长度相等。
例如:
redis> SETBIT bits-1 0 1 # bits-1 = 1001
(integer) 0
redis> SETBIT bits-1 3 1
(integer) 0
redis> SETBIT bits-2 3 1
(integer) 0
redis> BITOP xor xor-result bits-1bits-2
(integer) 1
redis> GETBIT not -result 0 # xor-result = 0100
(integer) 0
redis> GETBIT not -result 1
(integer) 1
redis> GETBIT not -result 2
(integer) 0
redis> GETBIT not -result 3
(integer) 0
2.4.5 计算Bitmaps中第一个值为targetBit的偏移量
命令:bitpos key targetBit [start][end]
返回:第一个值为的偏移量
例如:
10.3.34.101:6378> setbit testbit 0 1 testbit 111010
(integer) 0
10.3.34.101:6378> setbit testbit 1 1
(integer) 0
10.3.34.101:6378> setbit testbit 2 1
(integer) 0
10.3.34.101:6378> setbit testbit 3 0
(integer) 0
10.3.34.101:6378> setbit testbit 4 1
(integer) 0
10.3.34.101:6378> setbit testbit 5 0
(integer) 0
10.3.34.101:6378> bitpos testbit 0 第一个值为0的偏移量是3
(integer) 3
3.1 统计活跃用户数
将每个用户的id对应bitmaps上的一个下标,通过对活跃用户对应的位进行置位,就能用一个value记录所有的活跃用户信息。
假如我们有如下场景:
需要统计N天内访问网站的用户,连续N天访问网站的用户。
解决方案:
我们将每天访问网站的用户存储在一个bitmaps中,通过日期生成键,例如:unique:users:2017-07-11,这样我们就可以统计每天的用户访问情况,同时通过bitmaps的与或运算等功能统计出一个时间段内的活跃用户及连续N天访问网站用户等相关需求。
当记录的活跃用户数占总数的比例高的时候,bitmaps相比集合类型要节省非常多的内存,但是如果每天的活跃用户数很少,则bitmaps并不试用。下面以1亿用户,每天分别有5千万和10万来具体分析:
知识小贴士:作者尽心运营的知识星球社群【请点击:简道源码&&架构分析 加入】(可添加运营同学WX:wx454876882)持续拉新中...,定期的jdk与核心框架源码解析,主流行业解决方案与架构设计资料查阅与下载尽在其中。帮助行业新人和有志于技术的专业人士体系化的学习源码与系统架构,获取业界知名技术峰会和厂商对外公布的主流业务场景的解决方案。同时这个星球也是一个社群,大家可以在社群中结识有识之士,共同探讨,答疑解惑。希望可以通过这个星球帮助大家每日进步一点点,一年持续365天,共勉
本星球 聚焦于Java源码分析,架构解析。低代码,可扩展和高可用架构设计。帮助你更好地学编程,欢迎想进步的同学!仅精品案例的资料整理即物超所值。让我们大家一起每日进步一点点~~,你可以:
1. 阅读星球专属的编程知识和优质文章
2.JAVA知识从点和面,深度挖掘。通过点,形成面。提升自身的技术广度和深度。
3. 加入星球专属交流群,帮你找到学习伙伴、获取每日优质文章推送等
4.业界优秀案例资料学习及下载
5. 和伙伴们一起学习打卡,增加动力,共同进步
6.工作、学习和方法论。如何提升软实力,比如写文章、画架构图、技术产品的营销、社区的运营等等。
7.招聘、面试和晋升。如何提前准备面试,有什么套路?如何提升硬实力,少走弯路?
8.提供简历优化服务哟。本人常年招聘,也就面试了1000+程序员和架构师~~
9.解答你的疑问。
10.每日进步一点点(最重要的一点): 让自己与众不同,每天学习1-2小时源码和架构知识,365天后再回首,1年前的自己可能是个SB吧。用通勤的时间让自己成长,让优秀变成一种习惯。