Redis中的位操作

        简介

        redis的五种数据类型相信大家都非常清楚了,任何人问你基本都能脱口而出(string,hash,list,set,zset)。如果还不清楚,建议先看看redis基础,但是还有这几种类型很多人会忽略到。比如 Setbit(位操作),GEO(地理位置信息)等等。

        今天我们就来看一看setbit,看一看实际场景中到底是怎么用的,以及有哪些优势?我们先来回顾一下setbit吧,大家知道位操作,只有两个值,0和1,8个位正好是1b,所以位操作是非常节省空间的一种操作。

        setbit用法:

redis> SETBIT bit 10086 1  #把第10086个位置设置为1
(integer) 0
redis> GETBIT bit 10086    #获取第10086个位置的值  看是0还是1
(integer) 1
redis> GETBIT bit 100   # bit 默认被初始化为 0
(integer) 0

        其实就是把某个位标记为1或者0而已,但是它的好处在于非常节省空间。另外既然是位,就会涉及到或运算或者与运算。


        实例

        场景: 1亿个用户,每个用户登陆/做任意操作,记为 今天活跃,否则记为不活跃。 

        每周评出: 有奖活跃用户: 连续7天活动 

        每月评,等等... 

        其实简单说就是统计一下连续7天(或者连续30天)有多少人连续登陆过。


        咱们先来想一想传统的方案

        很容易就会想到只要用户登陆了,我在表中插入一条数据,并且记录上对应的日期,然后用mysql里面的记录来逐个判断,类似于这样:

Userid   date        active
1       2020-07-27   1
1       2020-07-26   1
2       2020-07-27   1
...

        但这样是存在一些问题的,主要的问题在于用户量高达1亿,每个用户登陆一次就远远的超过mysql的极限了,更不要说统计一星期了,而且用上group ,sum运算,计算也是非常慢的。所以在这种用户量大,而且统计比较简单的问题上,咱们可以运用位(setbit)操作来解决问题。 

        先分析一下思路,对于某一天来说,我们可以把这一天想像成一根小木棍,分成了不同的段落,每个段落对应的就是用户的位(因为有user_id),默认值都是0,只要有人登陆了,就把对应的用户的位置标为1即可。

        冷暖自知一抹茶ck

        如上图所示,这个就是一天的登陆情况,user_id为6和user_id为8的用户登陆过。其余的都为没有登陆过。因为这个是位操作,所以占的空间很小,1亿的用户,所占的空间也就不到12M。

        一天的问题咱们解决了,如何解决他们是否连续登陆过呢?

        我们可以用上多个"木棍"

        冷暖自知一抹茶ck

        我们可以把每一天作为一个键,然后每天对用户登陆状态进行标记,在最后用每天做一个"与运算"就可以准确的知道哪些用户连续登陆了。

        其实总结一下过程如下:

        1. 记录用户登陆 

        每天按日期生成一个位图, 用户登陆后,把user_id位上的bit值置为1

        2. 把1周的位图 and 计算 

        位上为1的,即是连续登陆的用户 

        代码实现如下:

redis 127.0.0.1:6379> setbit mon 100000000 0(integer) 0

redis 127.0.0.1:6379> setbit mon 3 1(integer) 0

redis 127.0.0.1:6379> setbit mon 5 1(integer) 0

redis 127.0.0.1:6379> setbit mon 7 1(integer) 0

redis 127.0.0.1:6379> setbit thur 100000000 0(integer) 0

redis 127.0.0.1:6379> setbit thur 3 1(integer) 0

redis 127.0.0.1:6379> setbit thur 5 1(integer) 0

redis 127.0.0.1:6379> setbit thur 8 1(integer) 0

redis 127.0.0.1:6379> setbit wen 100000000 0(integer) 0

redis 127.0.0.1:6379> setbit wen 3 1(integer) 0

redis 127.0.0.1:6379> setbit wen 4 1(integer) 0

redis 127.0.0.1:6379> setbit wen 6 1(integer) 0

redis 127.0.0.1:6379> bitop and  res mon feb wen(integer) 12500001

        如上例,优点为: 

        1、节约空间, 1亿人每天的登陆情况,用1亿bit,约1200WByte,约10M 的字符就能表示 

        2、计算方便


转自:

        Redis中的位操作

        BITOP命令 

冷暖自知一抹茶ck
请先登录后发表评论
  • 最新评论
  • 总共0条评论