세트를 사용하여 그날의 활성 사용자를 기록하면 사용자 수가 매우 많을 때 많은 공간을 낭비하게 됩니다. 따라서 redis는 사용자가 각 비트를 개별적으로 조작할 수 있도록 비트맵을 제공합니다. 다음 기사는 Redis의 비트맵을 이해하는 데 도움이 될 것입니다.
Bitmap, 즉 많은 수의 비트(각 비트는 0과 1만 가능)로 구성된 데이터 구조로 주로 일부 시나리오에서 공간 절약에 적합하며 의미 있는 기록입니다.
예를 들어 일부 대량의 bool 유형 액세스, 사용자의 365일 체크인 기록, 로그인된 경우는 1, 로그인되지 않은 경우는 0, 일반 키/값을 사용하여 저장하는 경우, 사용자가 크면 필요한 저장 공간도 매우 큽니다.
비트맵을 저장용으로 사용하면 365비트를 46바이트(조금 더 긴 문자열)로 변환하여 저장 공간을 많이 절약할 수 있습니다. 비트맵의 내용은 실제로 일반 문자열, 즉 바이트 배열입니다. get/set을 사용하여 전체 비트맵의 내용을 직접 얻고 설정할 수 있습니다. 또는 getbit/setbit를 사용하여 바이트 배열을 비트 배열로 처리할 수 있습니다. .을 다루다. [관련 권장사항:
Redis 동영상 튜토리얼]
일반적으로 문자열 설정은 set 명령을 사용합니다. 아래에서는 setbit를 사용하여 비트 배열을 설정하고 최종적으로 문자열을 얻는 형식으로 얻습니다.h의 이진 코드는 01101000이고 e의 이진 코드는 01100101임을 알 수 있습니다. 비트가 1인 위치에 주목하세요. 그런 다음 setbit를 수행합니다.
비트 배열의 순서와 문자의 비트 순서가 반대라는 점에 유의해야 합니다. h 문자의 각 1 위치는 1/2/4이고 e 문자는 9/10/13/15,
그래서 setbit를 사용하여 비트 배열을 설정하고 해당 비트 배열을 에 설정하겠습니다. 각 위치 (1/2/4/9/10/13/15) 1.
setbit data 1 1 setbit data 2 1 setbit data 4 1 setbit data 9 1 setbit data 10 1 setbit data 13 1 setbit data 15 1Set bit + get
마지막으로 데이터 키를 직접 가져오면 방금 가져온 것을 알 수 있습니다. 그,
setbit + get 조합을 무입금, 무입금이라고 합니다. 통합은 키 이름을 통해 모든 데이터를 직접 가져오는 것을 의미합니다.
마찬가지로 우리도 할 수 있습니다. 제로 저장 및 제로 페칭, 전체 저장 및 제로 페칭을 수행합니다. 정수 저장은 문자열을 직접 사용하여 전체 비트를 설정하는 것을 의미합니다. 배열의 경우 제로 검색은 비트 위치를 통해 비트를 얻는 것입니다.
제로 예금 및 제로 테이크보시다시피 setbit에 따라 w라는 키의 비트 배열을 설정하고 세 위치의 값만 1/2/로 설정합니다. 4 대 1, 아래와 같이 getbit w 3 이 있고, 세 번째 위치의 값을 구합니다. 기본값은 0 입니다. 비즈니스 관점에서 트리거하면 총 4 개가 있음을 알 수 있습니다.
0을 저장하고
오후에 보이듯이 w의 키에 h 문자를 직접 설정합니다. , getbit를 통해 w의 비트 배열에서 각 비트를 얻습니다. 위에서 얻은 내용과 h 문자를 볼 수 있습니다. 이진 내용은 1/2/4가 1이고 나머지는 0입니다.
Note
redis의 비트 배열은 자동으로 확장됩니다. 설정된 오프셋 위치를 초과하면 기존 콘텐츠 범위는 자동으로 비트 배열을 0으로 확장합니다. 즉, 확장된 비트는 다음과 같은 값을 갖습니다. 기본적으로 0입니다.
통계 및 검색(bitcount/bitpos)
我们可以通过bitcount统计用户一共签到了多少天,通过bitpos指令查找用户从哪一天开始第一次签到,
如果指定了范围参数[start, end],就可以统计在某个时间范围内用户签到了多少天以及用户自某天以后的哪天开始签到,
但是需要注意的是,start和end参数是字节索引,也就是说,指定的位范围必须是8的倍数,
而不能任意指定,所以我们无法直接计算某个月内用户签到了多少天,如果需要计算的话,
可以使用getrange命令取出该月覆盖的字节内容,然后在内存中进行统计,例如2月覆盖了10-12个字节,就使用 getrange w 8 12 。
127.0.0.1:6379> set w hello OK 127.0.0.1:6379> bitcount w # 所有字符中有多少个1 (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
之前介绍的 setbit / getbit 指定位的值都是单个位,如果要一次操作多个位,就必须使用管道来处理,
在redis3.2以后,提供了bitfield指令,可以一次对多个位进行操作,bitfield有三个子指令,分别是get/set/incrby, 都可以对指定位片段进行读写,
但是最多只能处理64个连续的位,如果超过64位,就需要使用多个子指令,bitfield可以一次执行多个子指令。
示例
下面对下图的位数组使用 bitfield 做一些操作
127.0.0.1:6379> bitfield w get u4 0 # 从第1个位开始取4个位,结果是无符号数(u) 1) (integer) 6 127.0.0.1:6379> bitfield w get u3 2 # 从第3个位开始取3个位,结果是无符号数(u) 1) (integer) 5 127.0.0.1:6379> bitfield w get i4 0 # 从第1个位开始取4个位,结果是有符号数(i) 1) (integer) 6 127.0.0.1:6379> bitfield w get i3 2 # 从第3个位开始取3个位,结果是有符号数(i) 1) (integer) -3
有符号数是指获取的位数组中的第一个位是符号位,剩下的才是值,如果第一位是1,就是负数,
无符号数表示非负数,没有符号位,获取的位数组全部都是值,有符号数最多可以获取64位,
无符号数只能获取63位,因为redis协议中的integer是有符号数,最大64位,不能传递64位的无符号值,
如果超出位数限制,redis就会告诉你参数错误。
上面的指令可以合并成一条指令,可以看到得到的结果是一样的,
bitfield w get u4 0 get u3 2 get i4 0 get i3 2
set修改
我们从第9个位开始,用8个无符号数替换已经存在的8个位,其实就是把第二个字符替换了,由e变成a(它的ASCII码是97),可以看到结果也变成了 hallo
127.0.0.1:6379> bitfield w set u8 8 97 1) (integer) 101 127.0.0.1:6379> get w "hallo"
incrby
incrby对指定范围的位进行自增操作,即++,这可能会发生溢出,如果增加了正数,会出现上溢出,如果增加的是负数,会出现下溢出,
redis默认的处理是折返,即如果出现了溢出,就将溢出的符号位丢掉,例如,如果是8位无符号数255,加1后就全部变成0,如果是8位有符号数127,加1后就溢出变成-128。
依然根据hello字符,来演示一下 incrby
127.0.0.1:6379> set w hello OK 127.0.0.1:6379> bitfield w get u4 2 # 从第3位开始取4个无符号整数,第一次是10 1) (integer) 10 127.0.0.1:6379> bitfield w incrby u4 2 1 1) (integer) 11 127.0.0.1:6379> bitfield w incrby u4 2 1 1) (integer) 12 127.0.0.1:6379> bitfield w incrby u4 2 1 1) (integer) 13 127.0.0.1:6379> bitfield w incrby u4 2 1 1) (integer) 14 127.0.0.1:6379> bitfield w incrby u4 2 1 1) (integer) 15 127.0.0.1:6379> bitfield w incrby u4 2 1 #到这里的时候,已经溢出折返成0了 1) (integer) 0
bitfield指令提供溢出策略子指令 overflow,用户可以选择溢出行为,默认是折返(wrap),还可以选择失败(fail) 即报错不执行,还有饱和截断(sat) 即超过范围就停留在最大或最小值,
overflow指令只影响接下来的第一条指令,这条指令执行完以后,溢出策略就会变成默认值 折返(wrap)。
饱和截断
127.0.0.1:6379> set w hello OK 127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1 1) (integer) 11 127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1 1) (integer) 12 127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1 1) (integer) 13 127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1 1) (integer) 14 127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1 1) (integer) 15 127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1 # 接下来的都将是保持最大值 1) (integer) 15 127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1 1) (integer) 15 127.0.0.1:6379> bitfield w overflow sat incrby u4 2 1 1) (integer) 15
失败不执行
127.0.0.1:6379> set w hello OK 127.0.0.1:6379> bitfield w overflow fail incrby u4 2 1 1) (integer) 11 127.0.0.1:6379> bitfield w overflow fail incrby u4 2 1 1) (integer) 12 127.0.0.1:6379> bitfield w overflow fail incrby u4 2 1 1) (integer) 13 127.0.0.1:6379> bitfield w overflow fail incrby u4 2 1 1) (integer) 14 127.0.0.1:6379> bitfield w overflow fail incrby u4 2 1 1) (integer) 15 127.0.0.1:6379> bitfield w overflow fail incrby u4 2 1 # 接下来的都是失败 1) (nil) 127.0.0.1:6379> bitfield w overflow fail incrby u4 2 1 1) (nil) 127.0.0.1:6379> bitfield w overflow fail incrby u4 2 1 1) (nil)
get/set/incrby一起执行
127.0.0.1:6379> bitfield w set u4 1 0 get u4 1 incrby u4 2 1 1) (integer) 0 2) (integer) 0 3) (integer) 1 127.0.0.1:6379> get w "\x04ello"
更多编程相关知识,请访问:编程视频!!
위 내용은 이 문서에서는 Redis(비트맵)의 비트맵을 이해하는 데 도움이 됩니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!