zoukankan      html  css  js  c++  java
  • redis位图

    <?php
    
    function frstr($str){
        return str_pad($str,8,'0',STR_PAD_LEFT);
    }
    
    
    $php='';
    $p= frstr(decbin(ord('p')));
    
    $h= frstr(decbin(ord('h')));
    
    $php=$p.$h.$p;
    
    echo $php;
    echo PHP_EOL;
    
    $len=strlen($php);
    $index=[];
    for($i=0;$i<$len;$i++){
        if($php[$i]==1){
            $index[]=$i;
        }
    }
    print_r($index);
    
    01110000,01101000,01110000
    Array
    (
        [0] => 1
        [1] => 2
        [2] => 3
        [3] => 9
        [4] => 10
        [5] => 12
        [6] => 17
        [7] => 18
        [8] => 19
    )
    

    01110000,01101000,01110000

    1,2,3,9,10,12,17,18,19 共9位需设置为1

    127.0.0.1:0>get p
    null
    
    127.0.0.1:0>setbit p 1 1
    "0"
    
    127.0.0.1:0>setbit p 2 1
    "0"
    
    127.0.0.1:0>setbit p 3 1
    "0"
    
    127.0.0.1:0>get p
    "p"
    
    127.0.0.1:0>setbit p 9 1
    "0"
    
    127.0.0.1:0>setbit p 10 1
    "0"
    
    127.0.0.1:0>setbit p 12 1
    "0"
    
    127.0.0.1:0>setbit p 17 1
    "0"
    
    127.0.0.1:0>setbit p 18 1
    "0"
    
    127.0.0.1:0>setbit p 19 1
    "0"
    
    127.0.0.1:0>get p
    "php"
    
    

    统计和查找

    Redis 提供了位图统计指令 bitcount 和位图查找指令 bitpos
    • bitcount 用来统计指定位置范围内 1 的个数
    • bitpos 用来查找指定范围内出现的第一个 0 或 1

    bitcount,bitpos

    127.0.0.1:0>bitcount p
    "9"
    127.0.0.1:0>bitcount p 0 0  #第一个字符中1的个数
    "3"
    127.0.0.1:0>bitcount p 0 1  #前2个字符中1的个数
    "6"
    127.0.0.1:0>bitpos p 0     #第一个0位
    "0"
    
    127.0.0.1:0>bitpos p 1		#第一个1位
    "1"
    
    127.0.0.1:0>bitpos p 1 1 1	#从第二个字符算起第一个1位
    "9"
    
    127.0.0.1:0>bitpos p 1 2 2  # 从第三个字符算起,第一个 1 位
    "17"
    

    bitfield

    bitfield(3.2版本之后) 有三个子指令,分别是 get/set/incrby,它们都可以对指定位片段进行读写,但是最多只能处理 64 个连续的位,如果超过 64 位,就得使用多个子指令,bitfield 可以一次执行多个子指令

    php

    01110000,01101000,01110000

    127.0.0.1:6379> get p
    "php"
    127.0.0.1:6379> bitfield p get u4 0  # 从第0个位开始取4个位  即为 0111  结果是无符号数 (u)
    1) (integer) 7
    127.0.0.1:6379> bitfield p get u3 2  #从第2个位开始取3个位 	即为110		结果是无符号数 (u)
    1) (integer) 6
    127.0.0.1:6379> bitfield p get i4 0  #从第0个位开始取4个位	即为0111		结果是有符号数 (i)
    1) (integer) 7
    127.0.0.1:6379> bitfield p get i3 2	  #从第2个位开始取3个    即为110		结果是有符号数 (i)
    1) (integer) -2
    127.0.0.1:6379> bitfield p  get u4 0  get u3 2  get i4 0     get i3 2
    1) (integer) 7
    2) (integer) 6
    3) (integer) 7
    4) (integer) -2
    

    所谓有符号数是指获取的位数组中第一个位是符号位,剩下的才是值
    如果第一位是 1,那就是负数
    无符号数表示非负数,没有符号位,获取的位数组全部都是值。有符号数最多可以获取 64 位,无符号数只能获取 63 位 (因为 Redis 协议中的 integer 是有符号数,最大 64 位,不能传递 64 位无符号值)
    如果超出位数限制,Redis 就会告诉你参数错误

    01110000,01101000,01110000
    把第二个h这只为p
    只需要把第11位由0->1,第12位由1->0即可
    setbit p 11 1
    setbit p 12 0
    127.0.0.1:6379> setbit p 11 1
    (integer) 0
    127.0.0.1:6379> setbit p 12 0
    (integer) 1
    127.0.0.1:6379> get p
    "ppp"
    
    127.0.0.1:6379> set p php
    OK
    127.0.0.1:6379> bitfield p set u8 8 97  #从第 8 个位开始,将接下来的 8 个位用无符号数 97 替换
    1) (integer) 104
    127.0.0.1:6379> get p
    "pap"
    

    incrby

    它用来对指定范围的位进行自增操作自增有可能出现溢出
    如果增加了正数,会出现上溢,如果增加的是负数,就会出现下溢出

    Redis 默认的处理是折返。如果出现了溢出,就将溢出的符号位丢掉
    如果是 8 位无符号数 255,加 1 后就会溢出,会全部变零。如果是 8 位有符号数 127,加 1 后就会溢出变成 -128

    bitfield p incrby u7 1 1
    
    127.0.0.1:6379> set p php
    OK
    127.0.0.1:6379> bitfield p incrby u7 1 1  # 从第7位开始,对接下来的1位无符号数 +1
    1) (integer) 113
    127.0.0.1:6379> get p
    "qhp"
    127.0.0.1:6379> bitfield p incrby u7 1 1
    1) (integer) 114       #r 的ascii码 为114
    127.0.0.1:6379> get p
    "rhp"
    127.0.0.1:6379> set  p php
    OK
    127.0.0.1:6379> bitfield p incrby u1 1 1
    1) (integer) 0
    127.0.0.1:6379> get p
    "0hp"
    127.0.0.1:6379> bitfield p incrby u1 1 1
    1) (integer) 1
    127.0.0.1:6379> get p
    "php"
    

    bitfield 指令提供了溢出策略子指令

    overflow,用户可以选择溢出行为,默认是折返 (wrap),还可以选择失败 (fail) 报错不执行,以及饱和截断 (sat),超过了范围就停留在最大最小值
    overflow 指令只影响接下来的第一条指令,这条指令执行完后溢出策略会变成默认值折返 (wrap)

    饱和截断 SAT

    p的二进制

    0111 0000

    127.0.0.1:6379> get p
    "p"
    127.0.0.1:6379> bitfield p overflow sat incrby u4 1 1
    1) (integer) 15
    127.0.0.1:6379> get p
    "x"
    127.0.0.1:6379> bitfield p overflow sat incrby u4 1 1
    1) (integer) 15
    127.0.0.1:6379> get p
    "x"
    127.0.0.1:6379> bitfield p overflow sat incrby u4 1 1 ## 保持最大值
    1) (integer) 15
    127.0.0.1:6379> get p
    "x"
    
    

    0111 0000

    执行

    bitfield p overflow sat incrby u4 1 1
    后变为

    0111 1000

    继续

    bitfield p overflow sat incrby u4 1 1

    因为采取了截断 (sat),超过了范围就停留在最大最小值

    失败不执行 FAIL SAT

    127.0.0.1:6379> set p p
    OK
    127.0.0.1:6379> bitfield p overflow fail incrby u5 1 1
    1) (integer) 29
    127.0.0.1:6379> get p
    "t"
    127.0.0.1:6379> bitfield p overflow fail incrby u5 1 1
    1) (integer) 30
    127.0.0.1:6379> get p
    "x"
    127.0.0.1:6379> bitfield p overflow fail incrby u5 1 1
    1) (integer) 31
    127.0.0.1:6379> get p
    "|"
    127.0.0.1:6379> bitfield p overflow fail incrby u5 1 1
    1) (nil)
    127.0.0.1:6379> get p
    "|"
    127.0.0.1:6379> 
    
    

    过程分析

    0111 0000

    执行

    bitfield p overflow fail incrby u5 1 1
    变为

    0111 0100

    ascii码为116 即为字符t

    然后继续执行

    bitfield p overflow fail incrby u5 1 1

    0111 1000

    ascii为120即为字符 x

    然后继续执行

    bitfield p overflow fail incrby u5 1 1
    变为

    0111 1100

    ascii 124即为字符 |

    再继续执行就会溢出,所以保留当前的最大值

  • 相关阅读:
    习题4.7利用vector实现数据复制
    习题4.18
    4.8编写一小段程序实现两vector是否相等的比较
    关于野指针
    学习c++的50条忠告
    c++头文件
    习题4.14
    容器和迭代器
    Android上C++对象的自动回收机制分析
    Windows下载Android源码
  • 原文地址:https://www.cnblogs.com/HKUI/p/10508017.html
Copyright © 2011-2022 走看看