美文网首页
5.【Redis系列】Redis的高级应用-位图

5.【Redis系列】Redis的高级应用-位图

作者: 773eeb0e0c48 | 来源:发表于2019-03-09 00:24 被阅读0次

    假设一个应用场景:我们需要记录用户一年的签到记录,签到了是1,没签是0,记录365天,当用户上亿后,存储空间是惊人的。
    为了解决这个问题,redis提供了位图的数据结构。这样每天的签到记录只占据一个位,365天就是365个位,46个字节完全可以容纳下。

    位图不是特殊的数据结构,它的内容就是普通的字符串,也就是byte数组,我们可以用set/get方法来设置和获取位图的内容,也可以使用位图操作getbit和setbit将byte数组看成位数组来处理。

    基本使用

    Redis 的位数组是自动扩展,如果设置了某个偏移位置超出了现有的内容范围,就会自动将位数组进行零扩充。

    接下来我们使用位操作将字符串设置为 hello (不是直接使用 set 指令),首先我们需要得到 hello 的 ASCII 码,用 Python 命令行可以很方便地得到每个字符的 ASCII 码的二进制值。

    >>> bin(ord('h'))
    '0b1101000'   # 高位 -> 低位
    >>> bin(ord('e'))
    '0b1100101'
    >>> bin(ord('l'))
    '0b1101100'
    >>> bin(ord('l'))
    '0b1101100'
    >>> bin(ord('o'))
    '0b1101111'
    
    image.png

    接下来我们使用 redis-cli 设置第一个字符,也就是位数组的前 8 位,我们只需要设置值为 1 的位,如上图所示,h 字符只有 1/2/4 位需要设置,e 字符只有 9/10/13/15 位需要设置。值得注意的是位数组的顺序和字符的位顺序是相反的。

    127.0.0.1:6379> setbit s 1 1
    (integer) 0
    127.0.0.1:6379> setbit s 2 1
    (integer) 0
    127.0.0.1:6379> setbit s 4 1
    (integer) 0
    127.0.0.1:6379> setbit s 9 1
    (integer) 0
    127.0.0.1:6379> setbit s 10 1
    (integer) 0
    127.0.0.1:6379> setbit s 13 1
    (integer) 0
    127.0.0.1:6379> setbit s 15 1
    (integer) 0
    127.0.0.1:6379> get s
    "he"
    

    上面这个例子可以理解为「零存整取」,同样我们还也可以「零存零取」,「整存零取」。「零存」就是使用 setbit 对位值进行逐个设置,「整存」就是使用字符串一次性填充所有位数组,覆盖掉旧值。

    零存零取
    127.0.0.1:6379> setbit w 1 1
    (integer) 0
    127.0.0.1:6379> setbit w 2 1
    (integer) 0
    127.0.0.1:6379> setbit w 4 1
    (integer) 0
    127.0.0.1:6379> getbit w 1  # 获取某个具体位置的值 0/1
    (integer) 1
    127.0.0.1:6379> getbit w 2
    (integer) 1
    127.0.0.1:6379> getbit w 4
    (integer) 1
    127.0.0.1:6379> getbit w 5
    (integer) 0
    
    零存零取
    127.0.0.1:6379> set w h  # 整存
    (integer) 0
    127.0.0.1:6379> getbit w 1
    (integer) 1
    127.0.0.1:6379> getbit w 2
    (integer) 1
    127.0.0.1:6379> getbit w 4
    (integer) 1
    127.0.0.1:6379> getbit w 5
    (integer) 0
    

    如果对应位的字节是不可打印字符,redis-cli 会显示该字符的 16 进制形式。

    127.0.0.1:6379> setbit x 0 1
    (integer) 0
    127.0.0.1:6379> setbit x 1 1
    (integer) 0
    127.0.0.1:6379> get x
    "\xc0"
    

    相关文章

      网友评论

          本文标题:5.【Redis系列】Redis的高级应用-位图

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