zoukankan      html  css  js  c++  java
  • Redis的bitmap从基础到业务

    1. 位与字节

      1个字节(byte)等于8个位(bit)。(计算机常识)。

     

    2. string与bitmap

    Redis里的bitmap是属于string这个数据类型里的。可以help进行查看bit相关api。

     

    3. bitmap的api

    3.1 setbit

    稍微解释下,setbit 三个参数,第一个是key,第二个是偏移量,也就是在第几个位(从0开始)上写value,第三个是值(这个值只支持0和1,因为是位,二进制。如果你写了大于1的数或者小于0的数,会报错的,不信的自己尝试。)

    get b1是个@符号,因为get取的不是位,所以不是0和1,而是ASCII码里的值,所以在ASCII码里对应的是@。(二进制转10进制,然后去ASCII码表里看,是@)

    setbit b1 1 1其实对应的是(因为每个字节8个位):0 1 0 0 0 0 0 0

    那我们在setbit b1 7 1,其实对应的就是:0 1 0 0 0 0 0 1,这时候gei b1就是A了,因为这个01000001在ASCII里对应的是大写A

     

    那么继续setbit b1 9 1呢?每个字节等于8位,你这个9相当于第10位,一个字节放不下了,这时候就会开辟两个字节来存储,会变成如下

    0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0

    然后get b1就又是@了

     

     

    3.2 Bitpos

    含义:查找第start字节到end字节之间的值为bit(0/1)的偏移量(匹配到的位的下标,从0开始)。

    bitpos 四个参数:key、要找的值(0/1)、从第几个字节(1个字节=8bit)开始找、到第几个字节结束

    注意:最后两个参数是从第几个字节到第几个字节,这里是字节,可不是位。刚才b1来看,我们setbit了三次,分别是1 7 9,1和7在第一个字节上(因为1字节=8位),9在第二个字节上。所以可以写:bitpos b1 1 0 1,代表在b1这个key上找第一个字节到第二个字节之间第一次值为1的位的下标(也称偏移量)。

     

    3.3 Bitcount

    含义:统计start到end字节中二进制值为1的个数。

     

    3.4 Bitop

    3.4.1 概述

    可以将多个bitmap进行按位与、按位或的操作,形成一个新的bit。

    为了演示按位与和按位或,这里初始化两个bitmap

         

    3.4.2 and

    将b2和b3两个key进行按位与操作,结果存到andkey里

    为什么andkey是个@?

    b2:0100 0001
    b3:0100 0010
    b2 & b3:
    0100 0000
    换成10进制是64,在ASCII码表里这不就是@嘛??!!!

     

    3.4.3 Or

    将b2和b3两个key进行按位或操作,结果存到orkey里

    跟上面按位与一样,自己算按位或后的二进制,在转换为10进制,得到67,ASCII码表里67是C

     

    4. 利用bitmap完成需求

    4.1 统计某用户登录天数

    需求:统计出每个用户的登录天数,且支持随即查看哪天是否登录过。

    需求分析:假设每年400天,1byte=8bit。那么每个字节能存8天的记录,400/8=50,也就是说50个字节就能记录某个人的一年登录状态。

     

    具体实现:
    假设zhangsan这个用户在第2、8、50、365天登录了,那么先setbit进去(假设zhangsan的用户id为123)

    # 第2天
    127.0.0.1:6380[2]> setbit 123 1 1
    # 第8天
    127.0.0.1:6380[2]> setbit 123 7 1
    # 第50天
    127.0.0.1:6380[2]> setbit 123 49 1
    # 第364天
    127.0.0.1:6380[2]> setbit 123 364 1

    然后我们可以采取getbit来获取某一天是否登录。还可以利用bitcount来统计他今年登录了多少天。

    # 查看123这个用户第50天是否登录
    127.0.0.1:6380[2]> getbit 123 49
    1
    # 查看123这个用户到今年目前为止最后16天登录了几天。之所以-2 -1能管用是因为反向索引,string篇幅说了
    127.0.0.1:6380[2]> bitcount 123 -2 -1
    1
    # 查看123这个用户今年前八天登录了几天
    127.0.0.1:6380[2]> bitcount 123 0 0
    2
    # 查看123这个用户今年全年登录了多少天
    127.0.0.1:6380[2]> bitcount 123
    4

    最后我们可以验证下到底用了多少byte存储的这个用户的全年记录,可以发现46字节而已。

    4.2 查看活跃用户总数

      需求:比如要查看活跃用户,指定日期区间,在这区间登录过就算活跃。

    需求分析:

    假设xiaoming在20200320和20200321这两天登录了,而xiaohong只在20200321这一天登录了。那要怎么存储呢?首先这个是要以日期作为key,value需要是用户id所占的bit偏移量位置,比如这两个用户xiaoming占用字节里的第2位,也就是1,因为从0开始。再比如xiaohong占用字节里的第10位,也就是9。

    PS:这个位怎么算都行,只要保证每个用户所占的字节偏移量不重复就行(也就是bit位置不重复就行),比如1000w个用户,那就每个用户id%1000w也能得到唯一的一个偏移量。

    现在知道xiaoming在第2位,小红在第10位,也知道了他们哪天登录过,所以上代码

     

    具体实现:

    # xiaoming在20200320登录
    127.0.0.1:6380[2]> setbit 20200320 1 1
    #  xiaoming在20200321登录
    127.0.0.1:6380[2]> setbit 20200321 1 1
    #  xiaohong在20200321登录
    127.0.0.1:6380[2]> setbit 20200321 9 1

    需求是:在这两天的任意一天登录过就算活跃用户,soeay,直接bitop按或运算完事。然后bitcount统计出人数。

    127.0.0.1:6380[2]> bitop or result 20200320 20200321
    # 结果2人
    127.0.0.1:6380[2]> bitcount result
    2

    疑问:连userid都没有我只统计人数有啥用?这需求不可能存在。
    回复:搞促销,登录送礼品。数据库里10E用户,你准备多少礼品?10E份?亏大发。僵尸用户可能占用一大半。所以需要统计出活跃用户,然后根据活跃用户的数量在乘以一个比例算出合适的礼品数量。

     

    转载:https://blog.csdn.net/ctwctw/article/details/105013817

    作者:小家电维修

    相见有时,后会无期。

  • 相关阅读:
    dddd
    asp.net web api rest风格与RPC风格调用
    使用ASP.NET WEB API文档来上传异步文件
    Fiddler2
    asp.net mvc3 局部页面@RenderBody @RenderPage@RenderSection使用方法详细说明
    paip.提升性能3倍使用栈跟VirtualAlloc代替堆的使用.
    paip.自适应网页设计 跟 响应式 设计的区别跟原理and实践总结
    paip.关于动画特效原理 html js 框架总结
    paip.utf8,unicode编码的本质输出unicode文件原理 python
    paip. 混合编程的实现resin4 (自带Quercus ) 配置 php 环境
  • 原文地址:https://www.cnblogs.com/lizexiong/p/14629370.html
Copyright © 2011-2022 走看看