>  기사  >  데이터 베이스  >  Redis의 비트맵에 대한 심층 분석(비트맵)

Redis의 비트맵에 대한 심층 분석(비트맵)

青灯夜游
青灯夜游앞으로
2021-12-02 10:17:184820검색

이 글은 Redis의 비트맵에 대해 소개하겠습니다. 도움이 되셨으면 좋겠습니다!

Redis의 비트맵에 대한 심층 분석(비트맵)

Redis의 비트맵은 여러 이진 비트로 구성된 배열입니다. 배열의 각 이진 비트에는 해당 오프셋(0부터 시작)이 있습니다. 비트맵. [관련 추천사항: Redis 동영상 튜토리얼]

사실 비트맵은 Redis에서 제공하는 새로운 데이터 유형이 아니라 문자열 유형의 확장입니다. 따라서 비트맵 명령은 문자열형 키에 직접 사용할 수 있고, 비트맵 명령으로 동작하는 키도 문자열형 명령으로 동작할 수 있습니다.

예를 들어 문자열 키 foo가 있습니다.

redis> set foo bar

1바이트는 8개의 이진 비트로 구성되므로 foo 키의 이진 형식은 다음과 같습니다.

Redis의 비트맵에 대한 심층 분석(비트맵)

SETBIT

SETBIT 명령을 통해, 오프셋의 바이너리 비트 설정 값은 비트맵에 대해 지정할 수 있으며 오프셋은 0보다 크거나 같아야 하며 값은 0 또는 1만 될 수 있습니다. 이 명령의 시간 복잡도는 O(1)입니다.

SETBIT 키 오프셋 값SETBIT key offset value

SETBIT 命令在对二进制位进行设置之后,将返回二进制位被设置之前的旧值作为结果。

假设现在想把 bar 变为 aar,只需如下两步操作:

redis> setbit foo 6 0
(integer) 1
redis> setbit foo 7 1
(integer) 0
redis> get foo"aar"

当执行 SETBIT 命令尝试对一个位图进行设置的时候,如果位图不存在,或者位图当前的大小无法满足,Redis 将对被设置的位图进行扩展,并将所有未被设置的二进制位的值初始化为 0。比如:

redis> setbit far 10 1

由于 far 并不存在,所以 Redis 会将 0~9 的二进制位设置为 0,因为 Redis 对位图的扩展操作是以字节为单位进行的,所以实际上 far 一共有 16 个二进制位,并不是 10 个,且 11~15 的二进制位也是 0。

基于这种情况,当指定的二进制位偏移量过大时,Redis 需要一次性分配完所有内存,这可能会造成 Redis 服务器阻塞。比如存储用户的性别,1 代表男性,0 代表女性,使用 ID 作为二进制偏移量,如果 ID 从 10000000001 开始的,就需要将用户 ID 减去 10000000000 再进行存储,否则会造成内存浪费。

GETBIT

使用 GETBIT 命令可以获取位图指定偏移量上的二进制位的值。此命令的时间复杂度是 O(1)。

GETBIT key offset

如果输入的偏移量超过了位图目前拥有的最大偏移量,将返回 0 作为结果。

BITCOUNT

通过 BITCOUNT 命令可以统计位图中值为 1 的二进制位数量。此命令的时间复杂度是 O(n)。

BITCOUNT key [start end]

在默认情况下,BITCOUNT 命令对位图包含的所有字节中的二进制位进行统计,也可以通过可选的 start 参数和 end 参数,让 BITCOUNT 只对指定字节范围内的二进制位进行统计(不是二进制偏移量)。比如,希望统计 ar 两个字节中值为 1 的二进制数量:

redis> bitcount foo 1 2
(integer) 7

start 和 end 参数也支持使用负数索引,下方的用法与上方的等效:

redis> bitcount foo -2 -1
(integer) 7

BITPOS

通过执行 BITPOS 命令,在位图中查找第一个被设置为指定值的二进制位,并返回这个二进制位的偏移量。

BITPOS key value [start end]

BITPOS 也接受可选的 start 参数和 end 参数,让 BITPOS 命令只在指定字节范围内的二进制位中进行查找。

redis> get foo"aar"redis> bitpos foo 1
(integer) 1
redis> bitpos foo 0
(integer) 0
redis> bitpos foo 0 1 2
(integer) 8
redis> bitpos foo 1 1 2
(integer) 9
redis> bitpos foo 1 -1 -1
(integer) 17

针对边界的处理:

  • 当尝试对一个不存在的位图或者一个所有位都被设置成了 0 的位图中查找值为 1 的二进制位时,BITPOS 命令将返回 -1 作为结果。
  • 如果在一个所有位都被设置成 1 的位图中查找值为 0 的二进制位,那么 BITPOS 命令将返回位图最大偏移量加上 1 作为结果

BITOP

通过 BITOP 命令,对一个或多个位图执行指定的二进制位运算,并将运算结果存储到指定的键中。

BITOP operation destkey key [key ...]

이진 비트를 설정한 후 SETBIT 명령은 이진 비트가 결과로 설정되기 전의 이전 값을 반환합니다. 🎜🎜이제 bar를 aar로 변경하려면 다음 두 단계만 필요하다고 가정해 보겠습니다. 🎜
redis> set foo1 bar
OK
redis> set foo2 aar
OK
redis> bitop or res foo1 foo2
(integer) 3
redis> get res"car"
🎜 비트맵을 설정하기 위해 SETBIT 명령을 실행할 때 비트맵이 존재하지 않거나 현재 비트맵 크기가 불가능할 경우 만족하면 Redis는 설정된 비트맵을 확장하고 설정되지 않은 모든 바이너리 비트의 값을 0으로 초기화합니다. 예: 🎜rrreee🎜far가 존재하지 않기 때문에 Redis는 이진수 비트를 0에서 9로 0으로 설정합니다. Redis는 비트맵을 바이트 단위로 확장하기 때문에 실제로 총 16개의 이진수가 있고 10개의 이진수가 없습니다. 11부터 15까지의 이진수도 0이다. 🎜
🎜이러한 상황에 따라 지정된 바이너리 비트 오프셋이 너무 크면 Redis는 모든 메모리를 한꺼번에 할당해야 하며 이로 인해 Redis 서버가 차단될 수 있습니다. 예를 들어 사용자의 성별을 저장할 때 1은 남성, 0은 여성을 나타내며 ID를 이진 오프셋으로 사용하여 ID가 ​​10000000001부터 시작하는 경우 사용자 ID에서 10000000000을 빼서 저장해야 합니다. 그렇지 않으면 낭비가 됩니다. 기억의. 🎜

🎜🎜GETBIT🎜🎜🎜🎜GETBIT 명령을 사용하여 비트맵의 지정된 오프셋에서 이진 비트 값을 가져옵니다. 이 명령의 시간 복잡도는 O(1)입니다. 🎜🎜GETBIT 키 오프셋🎜🎜입력 오프셋이 현재 비트맵이 소유한 최대 오프셋을 초과하는 경우 결과로 0이 반환됩니다. 🎜

🎜🎜BITCOUNT🎜🎜🎜🎜BITCOUNT 명령은 비트맵에서 값이 1인 이진 비트 수를 계산하는 데 사용할 수 있습니다. 이 명령의 시간 복잡도는 O(n)입니다. 🎜🎜BITCOUNT 키 [시작 끝]🎜🎜기본적으로 BITCOUNT 명령은 비트맵에 포함된 모든 바이트의 이진 비트를 계산합니다. 또한 선택적 시작 매개변수와 끝 매개변수를 전달할 수도 있습니다. 지정된 🎜byte🎜 범위 내의 이진 비트만 계산합니다(이진 오프셋은 제외). 예를 들어, ar의 2바이트에서 값이 1인 이진수의 개수를 계산하려고 합니다. 🎜rrreee🎜 시작 및 끝 매개변수는 음수 인덱스 사용도 지원합니다. 아래 사용법은 위와 같습니다. 🎜 rrreee

🎜🎜BITPOS🎜🎜🎜🎜BITPOS 명령을 실행하여 비트맵에서 지정된 값으로 설정된 첫 번째 이진 비트를 찾고 이 이진 비트의 오프셋을 반환합니다. 🎜🎜BITPOS 키 값 [시작 끝]🎜🎜BITPOS는 선택적 시작 매개변수와 끝 매개변수도 허용하므로 BITPOS 명령이 지정된 🎜byte🎜 범위 내의 이진 비트에서만 검색할 수 있습니다. 🎜rrreee🎜경계 처리: 🎜
  • 존재하지 않는 비트맵이나 모든 비트가 0으로 설정된 비트맵에서 값이 1인 이진 비트를 찾으려고 하면 BITPOS 명령은 -1을 다음과 같이 반환합니다. 결과.
  • 모든 비트가 1로 설정된 비트맵에서 값이 0인 이진 비트를 검색하면 BITPOS 명령은 비트맵의 최대 오프셋에 1을 더한 결과를 반환합니다.
  • 🎜🎜BITOP🎜🎜🎜🎜BITOP 명령을 사용하여 하나 이상의 비트맵에 대해 지정된 이진 비트 작업을 수행하고 작업 결과를 지정된 키에 저장합니다. 🎜🎜BITOP 작업 대상 키 [key ...]🎜

    operation 参数的值可以是 AND、OR、XOR、NOT 中的任意一个,这 4 个值分别对应逻辑并、逻辑或、逻辑异或和逻辑非 4 种运算,其中 AND、OR、XOR 这 3 种运算允许用户使用任意数量的位图作为输入,而 NOT 运算只允许使用一个位图作为输入。BITOP 命令在将计算结果存储到指定键中之后,会返回被存储位图的字节长度。

    当 BITOP 命令在对两个长度不同的位图执行运算时,会将长度较短的那个位图中不存在的二进制位的值看作 0。

    redis> set foo1 bar
    OK
    redis> set foo2 aar
    OK
    redis> bitop or res foo1 foo2
    (integer) 3
    redis> get res"car"

    Redis의 비트맵에 대한 심층 분석(비트맵)

    注意:BITOP 可能是一个缓慢的命令,它的时间复杂度是 O(N),在处理长字符串时应注意一下效率问题。

    应用场景

    用户行为记录器

    用用户 ID 作为偏移量,若用户做了某种行为则通过 SETBIT 将二进制位设置为 1,通过 GETBIT 判断用户是否做了某种行为,通过 BITCOUNT 可以知道有多少用户执行了行为。

    用户上线统计

    可以使用 SETBIT 和 BITCOUNT 来实现,以用户 ID 作为 key ,假设今天是上线统计功能开放的第一天,ID 为 1 的用户上线后就通过 SETBIT 1 0 1。当要计算此用户的总共以来的上线次数时,使用 BITCOUNT 命令就可以得出的结果。

    使用这种方式存储数据,即使 10 年后,1个用户就只占用几百字节的内存,它的处理速度依然很快。如果 bitmap 数据比较大,建议将 bitmap 拆分成多个小的 bitmap 分别进行处理。

    更多编程相关知识,请访问:编程入门!!

위 내용은 Redis의 비트맵에 대한 심층 분석(비트맵)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제