Redis位图

转载:Redis修行 — 位图实战 (juejin.cn)

Redis 中,位图 Bitmaps 不是实际的数据结构,而是 string 字符串类型上定义的一组 位操作

Redis 中字符串限制最大为 512MB,所以位图中最大可以设置 2^32 个不同的位(42.9亿个)。图位的最小单位是比特(bit),每个bit的值只能是01

1 基本命令

SETBIT key offset value

设置指定key的值在offset处的bit值,offset0开始(从左边开始)。返回值为在offset处原来的bit值。

127.0.0.1:6379> set h h        # 首先设置一个字符串,key=h,value=“h”,二进制为 01101000
OK
127.0.0.1:6379> get h
"h"
127.0.0.1:6379> setbit h 7 1   # 通过setbit修改h的offset=7位置的bit为1
(integer) 0
127.0.0.1:6379> get h          # 修改之后,二进制变成了 01101001,也就是"i"
"i"

GETBIT key offset

获取指定key值在offset处的bit值,offset0开始(从左边开始)。如果offset超出了当前位图的范围,则返回0

127.0.0.1:6379> get h        # “i”的二进制为 01101001
"i"
127.0.0.1:6379> getbit h 7   # offset=7的bit值为1
(integer) 1
127.0.0.1:6379> getbit h 8   # offset=8,超出了位图范围,返回的值为0
(integer) 0

BITCOUNT key [start end]

统计指定key值中被设置为1bit数。可以通过指定参数starend来限制统计范围。

注意:这里的starend不是指bit的下标,而是字节(byte)的下标。比如start1,则实际对应的bit下标为81byte = 8 bit)。

127.0.0.1:6379> set hi hi
OK
127.0.0.1:6379> get hi            # 二进制为 0110100001101001
"hi"
127.0.0.1:6379> bitcount hi       # 所有是1的位数:7个
(integer) 7
127.0.0.1:6379> bitcount hi 1 2   # 统计 01101001 中1的位数
(integer) 4

BITPOS key bit [start] [end]

统计首次出现的01bit位,可以通过startend来指定范围,同样是指字节的下标。

  • 在不存在的key或者空字符串中查找1,则返回-1
  • 在所有bit都为1中查找bit0的情况下,返回字符串最右边的第一个空位
127.0.0.1:6379> get nilkey          # 不存在的key
(nil)
127.0.0.1:6379> bitpos nilkey 1     # 在不存在的key中查首次出现1的位
(integer) -1
127.0.0.1:6379> setbit nilkey 0 0   # 空字符串
(integer) 0
127.0.0.1:6379> get nilkey
"\x00"
127.0.0.1:6379> bitpos nilkey 1
(integer) -1

BITOP operation destkey key [key …]

对一个或多个二进制位字符串进行操作,并将结果保存到 destkey 上。当某个字符串长度不够时,对应的位用0补上。

  • AND(逻辑与):都为1返回1,否则返回0
127.0.0.1:6379> set a a                   # 二进制 01100001
OK
127.0.0.1:6379> get a
"a"
127.0.0.1:6379> set c c                   # 二进制 01100011
OK
127.0.0.1:6379> get c
"c"
127.0.0.1:6379> bitop and a_and_c a c     # 与操作 01100001 -> a
(integer) 1
127.0.0.1:6379> get a_and_c
"a"

  • OR(逻辑或):只要有一个1就返回1,否则返回0
127.0.0.1:6379> set a a
OK
127.0.0.1:6379> get a
"a"
127.0.0.1:6379> set c c
OK
127.0.0.1:6379> get c
"c"
127.0.0.1:6379> bitop or a_or_c a c
(integer) 1
127.0.0.1:6379> get a_or_c
"c"
  • XOR(逻辑异或):当都是0或者都是1时返回0,否则返回1
127.0.0.1:6379> set a a
OK
127.0.0.1:6379> get a
"a"
127.0.0.1:6379> set c c
OK
127.0.0.1:6379> get c
"c"
127.0.0.1:6379> bitop xor a_xor_c a c
(integer) 1
127.0.0.1:6379> get a_xor_c
"\x02"
  • NOT(逻辑非):取反,1变成0,0变成1。只能传入一个要操作的key
127.0.0.1:6379> set a a
OK
127.0.0.1:6379> get a
"a"
127.0.0.1:6379> bitop not not_a a
(integer) 1
127.0.0.1:6379> get not_a
"\x9e"

2 利用位图统计签到

位图可以用于统计签到的场景。

大致思路

  1. 每天的签到情况作为一条记录,key 的格式为 sign:{yyyyMMdd}
  2. 将用户 id 作为偏移量 offset,通过 SETBIT 操作设置 id 位置的值为 1;
  3. 将用户 id 作为偏移量 offset,通过 GETBIT 操作查询这一天该用户是否签到;
  4. 通过 BITCOUNT 统计今天所有签到的用户数量;
  • 上述例子中我们默认用户id是数字类型。如果用户id是字符串的,那么可以将用户id作为key,取当天是今年的第几天作为偏移量offset,这样一条记录就是一个人全年的签到记录。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值