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

青灯夜游
풀어 주다: 2021-12-02 10:17:18
앞으로
4948명이 탐색했습니다.

이 글은 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을 더한 결과를 반환합니다.
  • < /ul>

    🎜🎜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으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿