Redis--Bitmap有序集合的语法和使用场景举例

文章目录

      • 前言
      • Bitmap概述
      • Bitmap命令介绍
      • 使用场景
      • 结尾

前言

  • Redis除了常见的五种数据类型之外,其实还有一些少见的数据结构,如Geo,HyperLogLog,Bitmap等。虽然它们少见,但是作用却不容小觑。本文将介绍Bitmap数据类型的语法和使用场景。
  • 下文将介绍bitmap的使用指令,以及其应用场景。

Bitmap概述

  • 在开发中,我们常常需要存放一些布尔类型的数据,比如我们的上班打卡记录,游戏签到记录等等。假设一个公司工作签到打卡的场景,一个员工今年第1,2,3天都工作了,需要对1,2,3做记录,如果对这三个整型数使用unsigned int来记录的话,那么需要3*4=12个字节,也就是96个bit的存储空间。而一个员工要这样记录一整年的数据,公司又不止一个员工,那么这个打卡功能就将耗费大量空间。
  • 为了节省空间,Redis提供了Bitmap,也就是位图这种数据结构。所谓位图,其实就是一个bit数组,对于一年上班打卡的记录,只需要提供一个365位的bit数组,如果第一天工作了,那就将第一位bit的0改为1即可。这样一来,一个人一年的打卡记录,只需要365bit位就可以记录完成了。位图按位来存储,大大节约了空间,其存储上限为2^32。

Bitmap命令介绍

  • bitmap设置某一位的值: SETBIT key offset value

    # 字母a的ASCII码是97,二进制就是01100001,一个字节 八个比特
    # 字母b的ASCII码是98,二进制就是01100010
    # 所以存入a只需要将0,6,7位设为1即可
    # 接着存入b就需要将10,14,15位设为1。
    setbit word 0 1
    setbit word 6 1
    setbit word 7 1
    setbit word 10 1
    setbit word 14 1
    setbit word 15 1
    
    # 除此之外,可以之间用字符串填充位的值
    set word ab 
    # 这个指令等价于上面的setbit
    
  • 获取bitmap中的数据,使用单个位操作获取位的值: getbit key offset

    getbit word 0 1
    getbit word 1 1
    
  • 统计bitmap指定位区间上,值为 1 的个数: bitcount key [start end]

    bitcount word    # 统计key为word的位图中有多少个1
    bitcount word 0 1 # 前两个字符中有几个1 
    
  • 返回bitmap中第一个值为bit的二进制位的位置,可以指定范围: bitpos key bit [start end]

    bitpos word 1  # 返回第一个为1的位
    bitpos word 0 0 1  # 返回前两个字符中第一个为0的位
    
  • 对一个或多个保存二进制位的字符串 key 进行位元操作(and,or,not,xor),并将结果保存到 destkey 上: BITOP operation destkey key [key …]

    bitop not new_word word # 对key为word的位图取反后存入new_word之中
    

Redis--Bitmap有序集合的语法和使用场景举例_第1张图片

使用场景

  • 需求:40亿个QQ号,限制1G的内存,如何对这些QQ号进行去重。
  • 实现方案:通过分析需求,有1G内存的限制,所以可以使用位图来节省空间。使用位图的话,一个qq号,即一个数字只需要占用一个bit(将这个bit设置为1),那么40亿个数字也就只需要400000000/8/1024/1024=476M,满足要求。
  • 代码实现:
    public class RedisBitmap {
      
       private static final String QQ_NUMBER = "QQ";
    
       /**
        * 将qq号码存入位图中
        * 即将位图对应qq号码的bit设为1
        * @param key
        * @param qq_number
        * @param jedis
        */
       public static void saveQQNumber(String key, long qq_number, Jedis jedis){
           jedis.setbit(key,qq_number,true);
       }
    
       /**
        * 获取bitmap中1的数量即可得到去重后的qq号数量
        * @param key
        * @param jedis
        */
       public static Long getCount(String key,  Jedis jedis){
           return jedis.bitcount(key);
       }
    
    }
    

结尾

  • bitmap常用于上面提及的去重,上班打卡,签到记录功能,使用bitmap可以减少很多不必要的存储空间。所以当出现类似的场景时,就好好使用它吧。

你可能感兴趣的:(Redis,redis,数据库,后端,java)