• Redis--位图BitMap


    一、BitMap是什么

    通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身,value对应0或1,我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间。

    二、Redis中的BitMap

    Redis从2.2.0版本开始新增了setbit、getbit、bitcount等几个bitmap相关命令。虽然是新命令,但是并没有新增新的数据类型,因为setbit等命令只不过是在set上的扩展。

    Redis的bitmap让我们可以实时的进行统计,并且极其节省空间。在模拟1亿2千8百万用户的模拟环境下,在一台MacBookPro上,典型的统计如“日用户数”(dailyunique users) 的时间消耗小于50ms, 占用16MB内存。

    Bitmap是一串连续的2进制数字(0或1),每一位所在的位置为偏移(offset),在bitmap上可执行AND,OR,XOR以及其它位操作。

    三、Redis中的命令

    1、setbit

      语法:setbit key offset value

      描述:

        对key所储存的字符串值,设置或清除指定偏移量上的位(bit)。

        位的设置或清除取决于 value 参数,可以是 0 也可以是 1 。

        当 key 不存在时,自动生成一个新的字符串值。

        字符串会进行伸展(grown)以确保它可以将 value 保存在指定的偏移量上。当字符串值进行伸展时,空白位置以 0 填充。

      注意:

        offset 参数必须大于或等于 0 ,小于 2^32 (bit 映射被限制在 512 MB 之内)。

        因为 Redis 字符串的大小被限制在 512 兆(megabytes)以内, 所以用户能够使用的最大偏移量为 2^29-1(536870911) , 如果你需要使用比这更大的空间, 请使用多个 key。

        当生成一个很长的字符串时, Redis 需要分配内存空间, 该操作有时候可能会造成服务器阻塞(block)。 在2010年出产的Macbook Pro上, 设置偏移量为 536870911(512MB 内存分配)将耗费约 300 毫秒, 设置偏移量为 134217728(128MB 内存分配)将耗费约 80 毫秒, 设置偏移量 33554432(32MB 内存分配)将耗费约 30 毫秒, 设置偏移量为 8388608(8MB 内存分配)将耗费约 8 毫秒。

    2、getbit

      语法:getbit key offset

      描述:

        对 key 所储存的字符串值,获取指定偏移量上的位(bit)。

        当 offset 比字符串值的长度大,或者 key 不存在时,返回 0

    3、bitcount

      语法:bitcount key [start] [end]

      返回值:被设置为 1 的位的数量

      描述:

        计算给定字符串中,被设置为 1 的比特位的数量

        一般情况下,给定的整个字符串都会被进行计数,通过指定额外的 start 或 end 参数,可以让计数只在特定的位上进行。

        start 和 end 参数的设置和 GETRANGE key start end 命令类似,都可以使用负数值: 比如 -1表示最后一个字节, -2 表示倒数第二个字节,以此类推。

        不存在的 key 被当成是空字符串来处理,因此对一个不存在的 key 进行 BITCOUNT 操作,结果为 0 。

    4、bitpos

    5、bitop

      语法:bitop operation destkey key [key ...]

        operation 可以是 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种:

      •   BITOP AND destkey key [key ...] ,对一个或多个 key 求逻辑并,并将结果保存到 destkey 。
      •   BITOP OR destkey key [key ...] ,对一个或多个 key 求逻辑或,并将结果保存到 destkey 。
      •   BITOP XOR destkey key [key ...] ,对一个或多个 key 求逻辑异或,并将结果保存到 destkey 。
      •   BITOP NOT destkey key ,对给定 key 求逻辑非,并将结果保存到 destkey 。

        除了 NOT 操作之外,其他操作都可以接受一个或多个 key 作为输入。    

      返回值:保存到 destkey 的字符串的长度,和输入 key 中最长的字符串长度相等

      描述:

        对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。

      注意:处理不同长度的字符串

        当 BITOP 处理不同长度的字符串时,较短的那个字符串所缺少的部分会被看作 0 。

        空的 key 也被看作是包含 0 的字符串序列。

      

    6、bitfield

    四、应用场景

    1、位图计数统计

    位图计数统计的是bitmap中值为1的位的个数。位图计数的效率很高,例如,一个bitmap包含10亿个位,90%的位都置为1,在一台MacBook Pro上对其做位图计数需要21.1ms。

    例子:日活跃用户

    为了统计今日登录的用户数,我们建立了一个bitmap,每一位标识一个用户ID。当某个用户访问我们的网页或执行了某个操作,就在bitmap中把标识此用户的位置为1。

    每次用户登录时会执行一次redis.setbit(daily_active_users, user_id, 1)。将bitmap中对应位置的位置为1,时间复杂度是O(1)。统计bitmap结果显示有今天有9个用户登录。Bitmap的key是daily_active_users,它的值是1011110100100101。

    因为日活跃用户每天都变化,所以需要每天创建一个新的bitmap。我们简单地把日期添加到key后面,实现了这个功能。例如要统计某一天有多少个用户访问,可以把这个bitmap的key设计为daily_active_users:2019-03-27。当用户访问进来,我们只是简单地在bitmap中把标识这个用户的位置为1,时间复杂度是O(1)。

    备注:

    Redis原生指令参考 http://redisdoc.com/index.html
    Redis python客户端 方法参考 http://redis-py.readthedocs.io/en/latest/#indices-and-tables

  • 相关阅读:
    烂泥:学习ubuntu之快速搭建LNMP环境
    烂泥:学习ubuntu远程桌面(二):远程桌面会话管理
    烂泥:学习ubuntu远程桌面(一):配置远程桌面
    烂泥:学习ssh之ssh密钥随身携带
    烂泥:学习ssh之ssh无密码登陆
    JS 获取浏览器窗口大小
    connect() failed (111: Connection refused) while connecting to upstream的解决
    css加载没效果,查看网络显示类型为 text/plain 的解决方法
    empty和isset的区别
    SQLite3命令操作大全
  • 原文地址:https://www.cnblogs.com/chjxbt/p/10615304.html
Copyright © 2020-2023  润新知