我们学习 Redis 时,都知道 Redis 支持以下几种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及 zset(sorted set:有序集合)。 现在介绍另一种比较少见的类型:位图。其实位图并不是一种特殊的数据结构,它的内容其实就是普通的字符串,也就是 byte 数组。我们可以使用普通的 get/set 直接获取和设置整个位图的内容,也可以使用位图操作命令 getbit/setbit 来处理。 在开发过程中,位图有什么作用呢?大家想一下,比如需要保存用户一年的签到记录,签了是 1,没签是 0,要记录 365 天。如果使用数据库表来存储,每个用户每年就会产生 365 条记录,当用户上亿的时候,需要的存储空间是惊人的。

基本使用
setbit/getbit 命令:
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"

        127.0.0.1:6379> getbit s 1
        (integer) 1

从上面的命令大家可以看到以 s 为 key 进行操作的,用 get 命令可以取出“he”的字符串,说明上面的 setbit 操作刚好凑成 he 的字符串,如果使用 getbit key offset 命令取指定偏移位置的值,则可以按照设置的取出来。

统计和查找
除了上面的命令当然不能满足开发的要求,Redis 还提供了位图统计指令 bitcount 和位图查找指令 bitpos,bitcount 用来统计指定位置范围内 1 的个数,bitpos 用来查找指定范围内出现的第一个 0 或 1。
比如我们可以通过 bitcount 统计用户一共签到了多少天,通过 bitpos 指令查找用户从哪一天开始第一次签到。如果指定了范围参数 [start, end],就可以统计在某个时间范围内用户签到了多少天,用户自某天以后的哪天开始签到。
遗憾的是, start 和 end 参数是字节索引,也就是说指定的位范围必须是 8 的倍数,而不能任意指定。因为这个设计,我们无法直接计算某个月内用户签到了多少天,而必须要将这个月所覆盖的字节内容全部取出来 (getrange 可以取出字符串的子串) 然后在内存里进行统计,这个非常繁琐。

    127.0.0.1:6379> set w hello
    OK
    127.0.0.1:6379> bitcount w
    (integer) 21
    127.0.0.1:6379> bitcount w 0 0  # 第一个字符中 1 的位数
    (integer) 3
    127.0.0.1:6379> bitcount w 0 1  # 前两个字符中 1 的位数
    (integer) 7
    127.0.0.1:6379> bitpos w 0  # 第一个 0 位
    (integer) 0
    127.0.0.1:6379> bitpos w 1  # 第一个 1 位
    (integer) 1
    127.0.0.1:6379> bitpos w 1 1 1  # 从第二个字符算起,第一个 1 位
    (integer) 9
    127.0.0.1:6379> bitpos w 1 2 2  # 从第三个字符算起,第一个 1 位
    (integer) 17

扫一扫有惊喜:
imagepng

  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:PipeSoloSymWide 等,欢迎大家加入,贡献开源。

    3121 引用 • 3882 回帖 • 656 关注
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    121 引用 • 186 回帖 • 926 关注
  • 位图
    2 引用 • 16 回帖
  • BitMap
    1 引用
感谢    关注    收藏    赞同    反对    举报    分享