redis数据操作-位图

背景

在我们平时开发中可能会经常遇到这么一种场景,就是获取用户一段时间内的行为记录,这些行为记录的状态都为Boolean类型,要么是有要么就是无,例如用户的签到记录、某段时间内的打卡记录等等,面对这种场景我们大多数可能都是数据库直接查询然后转换为一个Boolean数组返回前端,数据量少和并发低的情况这么操作是没有问题的,但是并发一高或者数据量非常庞大的时候这么直接统计引发的问题可就不少了,在这种场景下redis的位图可以发挥极其强大的功效。

redis位图简介

redis位图是由多个二进制位组成的数组结构,数组中每个二进制位都有与其对应的下标也就是偏移量,用户可以通过下标对位图中的二进制位数组某一个或者某几个二进制位进行操作,例如将1->0,将0->1。
位数组
对于位数组我们可以做以下操作:

  • 设置其中某一个位的为1或者是0。
  • 统计当前位数组中有多少个1。
  • 获取指定下标的位值。
  • 获取第一个1或者是0的位下标。
  • 获取某一段区域内的位数组所对应的数值。

redis位图基本操作

设置位数组某个下标的值,我们设置bit_user这个key的下标5、7、9为1,指令为SETBIT。

127.0.0.1:6379> SETBIT bit_user 5 1
127.0.0.1:6379> SETBIT bit_user 7 1
127.0.0.1:6379> SETBIT bit_user 9 1

统计当前bit_user这个位数组有多少个1,指令为BITCOUNT。

127.0.0.1:6379> BITCOUNT bit_user 0 8
(integer) 3

BITCOUNT指令后面还可以跟start和end参数,表示统计下标start->end区域内的位值为1的数量。

查询位数组下标为3、4、7的值,指令为GETBIT。

127.0.0.1:6379> GETBIT bit_user 3
(integer) 0
127.0.0.1:6379> GETBIT bit_user 4
(integer) 0
127.0.0.1:6379> GETBIT bit_user 7
(integer) 1

查询第一个出现1位或者0位的下标,指令为BITPOS。

127.0.0.1:6379> BITPOS bit_user 0
(integer) 0
127.0.0.1:6379> BITPOS bit_user 1
(integer) 5

BITPOS指令后面还可以跟start和end参数,表示查询下标start->end区域内的第一次出现1或者是0的下标。

查询从第一位开始获取21个位,结果是无符号位的数字,指令为BITFIELD。

127.0.0.1:6379> BITFIELD bit_user get u21 0
1) (integer) 43008

BITFIELD这个指令可以一次获取多个数,例如BITFIELD bit_user get u21 0 get u21 1,还有将某一段的位图用一个数字去替换掉,例如BITFIELD bit_user set u8 0 99该指令表示将bit_user从第八个位开始用无符号位99替换八个位。

线上实际案例

我们之前做过一个活动叫做21天打卡计划,用户每次进入打卡页都需要展示当前正在进行中的21天打卡具体情况,当前进行到第几天,前面已过的卡点打卡情况,当前21天打卡计划里已经累计打卡了多少次,最开始我们是直接从数据库中取,然后在代码里面去进行统计,之后参与打卡人数逐渐增多,并且这个打卡访问具有极端性,在上午8-10点访问量在某个点会非常高,所以最初的方案已经不可取了。

优化方案:
采用redis的位图实现,每个用户21打卡数据都以位图储存在redis中,用户每次打卡过后都将对应位置为1,例如用户第七天打卡那就使用指令SETBIT bit_user 7 1,那么上述的需求就变得非常简单了。

  1. 查询该用户21天已经累计打过多少次卡直接使用bitcount指令即可得到,无需再去进行数据库查询或者业务代码统计。
  2. 查询前面n天的打卡情况,使用BITFIELD指令得到数值然后在转化为二进制即可。
  3. 如果要展示最近一周的打卡次数,依旧使用BITCOUNT,指令后面跟上下标即可,BITCOUNT bit_user x-7 x,x为当前所在的下标位置。

参考文献:
1.Redis使用手册
2.Redis 深度历险:核心原理与应用实践

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值