美文网首页
Redis高级功能之 - bitmap

Redis高级功能之 - bitmap

作者: kyo1992 | 来源:发表于2021-04-12 08:27 被阅读0次

亿级活跃用户场景

  • 实现日活跃统计
  • 实现周活跃统计
  • 为了增强用户粘性,增加一个连续打卡发放积分功能,怎么实现连续打卡用户统计。

传统做法

定义一个表,记录每个用户的每次登陆时间

user_id login_day
400 2019-10-22
500 2019-10-22
1000 2019-10-21

统计2019-10-21和2019-10-22两天有登陆的用户数量sql

select count(*) from login_stats today_stats inner join login_stats yesterday_stats on
      today_stats.user_id = yesterday_stats.user_id
      where 
      today_stats.login_day = '2019-10-22' and
      yesterday_stats.login_day = '2019-10-21';

在千万级甚至亿级日活跃的应用中,这张表每天新增数据量就会达到千万级甚至亿级规模,大表的操作性能是非常差的。

Redis bitmap

在使用getrange和setrange对字符串操作时,是基于字节实现的。
Redis提供更加精细的操作,可以针对某个字节的bit位进行操作。
bit位的值只有两个,0 和 1.
Redis操作指令

setbit key offset 0|1   # offset为索引,能精确定位到某个bit
getbit key
bitcount key
bitop and|or key

一个例子
some_value:
0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 ...
offset:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ...
每个offset对应一个bit
offset的上限是 2^32-1 约等于 42亿
setbit的过程,value值会发生动态扩容。

127.0.0.1:6379> setbit key 1 1  # 第一次设置值,offset为1,处于第一个字节的第2个bit,值只需要分配一个字节
(integer) 0
127.0.0.1:6379> strlen key
(integer) 1
127.0.0.1:6379> setbit key 8 1 # 第二次设置值,offset为8,处于第二个字节的第1个bit,值发生扩容.
(integer) 0
127.0.0.1:6379> strlen key
(integer) 2

如何实现文中开头的三个场景统计

首先用户id必须是个整型,如果用户id起始值过大,可以做一个偏移;用户id不全是整型,可以用hash算法得出自然数然后取模。 把用户id作为 offset。

计算日活跃
# 设置100 103 109用户在2019:0521登录
127.0.0.1:6379> setbit login:2019:0521 100 1
(integer) 0
127.0.0.1:6379> setbit login:2019:0521 103 1
(integer) 0
127.0.0.1:6379> setbit login:2019:0521 109 1
(integer) 0
127.0.0.1:6379> bitcount login:2019:0521 0 -1  # 统计2019:0521登录过的用户
(integer) 3
# 设置100 109用户在2019:0522登录
127.0.0.1:6379> setbit login:2019:0522 100 1
(integer) 0
127.0.0.1:6379> setbit login:2019:0522 109 1
(integer) 0
127.0.0.1:6379> bitcount login:2019:0522  # 统计2019:0522登录过的用户
(integer) 2
# 设置100用户在2019:0523登录
127.0.0.1:6379> setbit login:2019:0523 100 1
(integer) 0
127.0.0.1:6379> bitcount login:2019:0523  # 统计2019:0523登录过的用户
(integer) 2
计算连续多日活跃人数
# 连续两日
127.0.0.1:6379> bitop and login:2019:0521 login:2019:0522
(integer) 14
127.0.0.1:6379> bitop and login:2019:0521-0522  login:2019:0521 login:2019:0522
(integer) 14
127.0.0.1:6379> bitcount login:2019:0521-0522
(integer) 2
# 连续三日
127.0.0.1:6379> bitop and login:2019:0521-0523  login:2019:0521 login:2019:0522 login:2019:0523
(integer) 14
127.0.0.1:6379> bitcount login:2019:0521-0523
(integer) 1
计算多日其中一日有活跃的人数,例如周活跃统计
127.0.0.1:6379> bitop or orlogin:2019:0521-0523  login:2019:0521 login:2019:0522 login:2019:0523
(integer) 14
127.0.0.1:6379> bitcount orlogin:2019:0521-0523
(integer) 3
offset开辟1亿所需字节数
127.0.0.1:6379> setbit key1e 100000000 1
(integer) 0
127.0.0.1:6379> strlen key1e
(integer) 12500001
127.0.0.1:6379> type key1e
string
127.0.0.1:6379> object encoding key1e
"raw"

字节数为 1250w Byte,约等于12MB,还是很省内存的。

使用注意事项

  • bitcount操作的时间复杂度是O(n),在大并发或者offset非常大的情况下使用会有性能问题。
  • bitmap适合海量数据场景下使用,如果要统计的数据不多,或者offset比较分散,会占用较多的内存,可能使用关系型数据库统计较好。
  • 其实只要是记录一些二元操作,都可以使用bitmap统计。

相关文章

  • Redis高级功能之 - bitmap

    亿级活跃用户场景 实现日活跃统计 实现周活跃统计 为了增强用户粘性,增加一个连续打卡发放积分功能,怎么实现连续打卡...

  • Redis第4课:Redis 的高级功能

    本文我们将介绍 Redis 的高级功能,比如:慢查询、PipeLine、BitMap、HyperLogLog、发布...

  • 【SpringBoot DB 系列】Redis 高级特性之 Bi

    【SpringBoot DB 系列】Redis 高级特性之 Bitmap 使用姿势及应用场景介绍 前面介绍过 re...

  • 瑞士军刀Redis

    瑞士军刀Redis 一 功能介绍:慢查询 pipeline 发布订阅 bitmap HyperLogLog ...

  • redis bitmap 坑 字节内部逆序

    记一笔redis bitmap 的坑获取redis的bitmap 为1 的id

  • Redis 高级功能

    一、Redis 管道技术 1.1 背景 想象一下,现在需要向 Redis 中添加大量的 KV 对,可以通过直接调用...

  • redis高级功能-redis事务

    Redis事务 Redis事务是一组命令的集合,也是Redis的最小执行单位之一。一个事务的所有命令,要么都执行,...

  • 布隆过滤器

    小空间做大事情 go-zero 里面用到了redis的 bitmap数据类型。其实应该说redis的bitmap在...

  • redis高级功能-队列

    redis队列实现高并发下数据ID读取 id数据预生成id数据预生成:根据业务逻辑,预生成ID数据,通过redis...

  • Redis高级

    Redis高级 发布订阅 Redis提供了发布订阅功能,可以用于消息的传输 Redis的发布订阅机制包括三个部分,...

网友评论

      本文标题:Redis高级功能之 - bitmap

      本文链接:https://www.haomeiwen.com/subject/ryzmkltx.html