Redis의 다양한 데이터 유형과 클러스터 관련 지식에 대해 이야기해 보겠습니다.

青灯夜游
풀어 주다: 2022-01-10 18:49:19
앞으로
1497명이 탐색했습니다.

이 글은 Redis의 다양한 데이터 유형과 클러스터 관련 지식을 소개하고 클러스터를 이해하는 데 도움이 되기를 바랍니다.

Redis의 다양한 데이터 유형과 클러스터 관련 지식에 대해 이야기해 보겠습니다.

다양한 데이터 유형

string 유형이 간단하고 편리하며 공간 사전 할당을 지원합니다. 즉, 매번 더 많은 공간이 할당되므로 다음에 문자열이 길어지면 문제가 발생합니다. 물론 남은 공간이 충분하다면 추가 신청은 필요하지 않습니다. [관련 권장사항: Redis 동영상 튜토리얼]

List 유형은 간단한 메시지 큐를 구현할 수 있지만 메시지 손실이 있을 수 있으며 ACK 모드를 지원하지 않는다는 점에 유의하세요.

Hash 테이블은 약간 관계형 데이터베이스와 비슷하지만, 해시 테이블이 점점 커지면 hgetall과 같은 문은 사용을 피하는 것이 좋습니다. 많은 양의 데이터를 요청하면 Redis가 차단되므로 주의하시기 바랍니다. 뒤에 있는 형제들이 기다려야 할 것입니다.

set 세트 유형은 일부 통계를 수행하는 데 도움이 될 수 있습니다. 예를 들어 특정 날짜의 활성 사용자 수를 계산하려는 경우 세트는 다음과 같은 몇 가지 멋진 작업을 지원합니다. 집합 간 차이를 얻을 수 있는 sdiff, sunion은 집합 간 합집합을 얻을 수 있고 많은 기능을 가지고 있지만 이러한 작업에는 약간의 CPU 및 IO 리소스가 필요하므로 주의해야 합니다. 블로킹하므로 큰 집합 사이의 연산 멋진 연산을 사용할 때 주의하세요.

zset 정렬이 가능하기 때문에 상단과 같은 응용 시나리오가 많습니다. 좋아요를 누른 xx명의 사용자, 대기열 지연 등

bitmap 비트맵의 장점은 특히 특정 날짜에 로그인한 사용자 수, 특정 사용자의 로그인 여부 등 일부 통계를 수행할 때 공간을 절약할 수 있다는 것입니다. 비트맵을 사용하지 않는 경우, 당신은 세트를 사용하는 것을 생각할 수도 있습니다.

SADD day 1234//签到就添加到集合
SISMEMBER day 1234//判断1234是否签到
SCARD day   //有多少个签到的
로그인 후 복사

set는 기능적으로는 만족스럽지만 비트맵에 비해 저장공간을 더 많이 차지합니다. set의 맨 아래 레이어는 주로 정수 컬렉션이나 해시 테이블로 구성되어 있으며 일반적으로 데이터 양이 매우 적을 경우에만 사용됩니다. 512개 미만의 요소, 그리고 요소는 모두 정수여야 합니다. 집합의 경우 정수 집합의 데이터는 더 작고 메모리에서 연속적입니다. 쿼리는 이진 검색만 가능하며 시간 복잡도는 O(logN)입니다. 여기서 해시테이블은 값이 null을 가리키고 컬렉션이기 때문에 충돌이 없다는 점을 제외하면 Redis의 5가지 주요 데이터 유형의 해시와 동일합니다. Rehash 관련 문제를 고려해야합니다. 사용자 로그인 문제에 대해서는 좀 거리가 멀군요. 사용자가 많을 때 set은 반드시 해시테이블을 사용하게 됩니다. 실제로 각 요소는 dictEntry 구조입니다

typedef struct dictEntry {
    // 键
    void *key;
    // 值
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
    } v;
    // 指向下个哈希表节点,形成链表
    struct dictEntry *next;

} dictEntry;
로그인 후 복사

구조, 당신은 무엇을 볼 수 있습니까? 우선, 값이 Union(값 없음)과 Next(충돌 없음)가 비어 있지만 구조 자체에는 공간과 키가 필요합니다. 이 점유 공간은 실제이며 비트맵을 사용하면 1비트이면 충분합니다. 숫자를 나타내고 공간을 절약해 줍니다. 비트맵을 설정하고 계산하는 방법을 살펴보겠습니다.

SETBIT day 1234 1//签到
GETBIT day 1234//判断1234是否签到
BITCOUNT day//有多少个签到的
로그인 후 복사

bf redis4.0 이후에 지원되는 Bloom 필터 RedisBloom 인데 해당 모듈을 별도로 로드해야 합니다. 물론 위의 비트맵을 기반으로 자체 Bloom 필터를 구현할 수도 있지만 Redis는 이미 지원하고 있습니다. 예, RedisBloom을 통해 개발 시간을 단축할 수 있습니다. Bloom 필터의 기능은 무엇입니까? 여기서는 RedisBloom의 관련 사용법을 자세히 살펴보겠습니다.

# 可以通过docker的方式快速拉取镜像来玩耍
docker run -p 6379:6379 --name redis-redisbloom redislabs/rebloom:latest
docker exec -it redis-redisbloom bash
redis-cli
# 相关操作
bf.reserve sign 0.001 10000
bf.add sign 99 //99这个用户加入
bf.add exists 99//判断99这个用户是否存在
로그인 후 복사

블룸 필터에는 오판이 있기 때문에 모든 bf는 맞춤 오판 비율을 지원합니다. 0.001은 오판 비율을 나타내고, 10000은 블룸 필터가 저장할 수 있는 요소 수를 나타내며, 실제 저장된 요소 수를 초과하면 false입니다. 긍정적인 비율이 높아질 것입니다.

HyperLogLog는 통계에 사용할 수 있으며, 2^64개 요소를 계산하는 데 12KB의 메모리만 필요하다는 장점이 있습니다. 실제로는 주로 UV와 같은 카디널리티 통계에 관한 것입니다. 기능적으로 말하면 UV는 세트 또는 해시를 사용하여 저장할 수 있지만 단점은 스토리지를 소비하고 공간을 절약하려는 경우 쉽게 큰 키가 될 수 있다는 것입니다. 12KB도 사용할 수 있습니다. 공간 비트맵은 12*1024*8=98304개의 요소만 계산할 수 있지만 HyperLogLog는 2^64개의 요소를 계산할 수 있습니다. 그러나 이러한 강력한 기술에는 실제로 확률에 따른 오류와 표준 오류가 있습니다. 계산 비율은 0.81%입니다. 대용량 데이터가 계산되고 정확도 요구 사항이 그다지 높지 않은 시나리오에서 HyperLogLog는 여전히 공간 절약에 매우 좋습니다.

PFADD uv 1 2 3 //1 2 3是活跃用户
PFCOUNT uv //统计
로그인 후 복사

GEO 是可以应用在地理位置的业务上,比如微信附近的人或者附近的车辆等等,先来看一下如果没有GEO 这种数据结构,你如何知道你附近的人?首先得上报自己的地理位置信息吧,比如经度 116.397128,纬度 39.916527,此时可以用 string、hash 数据类型存储,但是如果要查找你附近的人,string 和 hash 这种就无能为例了,你不可能每次都要遍历全部的数据来判断,这样太耗时了,当然你也不可能通过 zset 这种数据结构来把经纬度信息当成权重,但是如果我们能把经纬度信息通过某种方式转换成一个数字,然后当成权重好像也可以,这时我们只需通过zrangebyscore key v1 v2也可以找到附近的人。真的需要这么麻烦吗?于是 GEO 出现了,GEO 转换经纬度为数字的方法是“二分区间,区间编码”,这是什么意思呢?以经度为例,它的范围是[-180,180],如果要采用3位编码值,那么就是需要二分3次,二分后落在左边的用0表示,右边的用1表示,以经度是121.48941 来说,第一次是在[0,180]这个区间,因此记1,第二次是在[90,180],因此再记1,第三次是在[90,135],因此记0。纬度也是同样的逻辑,假设此时对应的纬度编码后是010,最后把经纬度合并在一起,需要注意的是经度的每个值在偶数位,纬度的每个值在奇数位。

1 1 0   //经度
 0 1 0  //纬度
------------
101100 //经纬度对应的数值
로그인 후 복사

原理是这样,我们再来看看 redis 如何使用 GEO:

GEOADD location 112.123456 41.112345 99 //上报用户99的地理位置信息
GEORADIUS location  112.123456 41.112345 1 km ASC COUNT 10 //获取附近1KM的人
로그인 후 복사

搞懂集群

生产环境用单实例 redis 的应该比较少,单实例的风险在于:

  • 单点故障即服务故障,没有backup

  • 单实例压力大,又要提供读,又要提供写

于是我们首先想到的就是经典的主从模式,而且往往是一主多从,这是因为大部分应用都是读多写少的情况,我们的主负责更新,从负责提供读,就算我们的主宕机了,我们也可以选择一个从来充当主,这样整个应用依然可以提供服务。

复制过程的细节

当一个 redis 实例首次成为某个主的从的时候,这时主得把数据发给它,也就是 rdb 文件,这个过程 master 是要 fork 一个子进程来处理的,这个子进程会执行 bgsave 把当前的数据重新保存一下,然后准备发给新来的从,bgsave 的本质是读取当前内存中的数据然后保存到 rdb 文件中,这个过程涉及大量的 IO,如果直接在主进程中来处理的话,大概率会阻塞正常的请求,因此使用个子进程是个明智的选择。

那 fork 的子进程在 bgsave 过程中如果有新的变更请求会怎么办?

严格来说子进程出来的一瞬间,要保存的数据应该就是当时那个点的快照数据,所以是直接把当时的内存再复制一份吗?不复制的话,如果这期间又有变更改怎么办?其实这要说到写实复制(COW)机制,首先从表象上来看内存是一整块空间,其实这不太好维护,因此操作系统会把内存分成一小块一小块的,也就是内存分页管理,一页的大小一般是4K、8K或者16K等等,redis 的数据都是分布在这些页面上的,出于效率问题,fork 出来的子进程是和主进程是共享同一块的内存的,并不会复制内存,如果这期间主进程有数据变更,那么为了区分,这时最快捷的做法就是把对应的数据页重新复制一下,然后主的变更就在这个新的数据页上修改,并不会修改来的数据页,这样就保证了子进程处理的还是当时的快照。

以上说的变更是从快照的角度来考虑的,如果从数据的一致性来说,当快照的 rdb 被从库应用之后,这期间的变更该如何同步给从库?答案是缓冲区,这个缓冲区叫做 replication buffer,主库在收到需要同步的命令之后,会把期间的变更都先保存在这个缓冲区中,这样在把 rdb 发给从库之后,紧接着会再把 replication buffer 的数据也发给从库,最终主从就保持了一致。

replication buffer不是万能的补给剂

我们来看看 replication buffer 持续写入的时间有多长。

  • 我们知道主从同步的时候,主库会执行 fork 来让子进程完成相应地工作,因此子进程从开始执行 bgsave 到执行完毕这期间,变更是要写入 replication buffer 的。

  • rdb 生成好之后,需要把它发送给从库,这个网络传输是不是也需要耗点时间,这期间也是要写入 replication buffer 的。

  • RDB를 받은 후 슬레이브 라이브러리는 RDB를 메모리에 적용해야 하며 이 기간 동안 슬레이브 라이브러리가 차단되어 서비스를 제공할 수 없으므로 이 기간 동안 복제 버퍼도 작성해야 합니다.

복제 버퍼는 버퍼이기 때문에 크기가 제한되어 있습니다. 위의 세 단계 중 하나라도 시간이 오래 걸리면 복제 버퍼가 빠르게 증가하게 됩니다(정상적인 쓰기가 수행되는 경우). 버퍼가 한도를 초과하면 마스터 데이터베이스와 슬레이브 데이터베이스 간의 연결이 끊어지며, 연결이 끊어진 후 슬레이브 데이터베이스가 다시 연결되면 복제가 다시 시작되고 동일한 긴 복제 단계가 반복됩니다. 복제 버퍼 크기는 여전히 매우 중요하며 일반적으로 쓰기 속도, 초당 쓰기 양, 네트워크 전송 속도 등의 요소를 기반으로 종합적으로 판단해야 합니다.

슬레이브 데이터베이스 네트워크가 좋지 않고 마스터 데이터베이스 연결이 끊어지면 어떻게 해야 하나요?

일반적으로 마스터와 슬레이브 간의 연결이 설정되어 있는 한 마스터 데이터베이스에 대한 후속 변경 사항은 슬레이브 데이터베이스에서 직접 재생하기 위해 슬레이브 데이터베이스로 직접 전송될 수 있지만 네트워크 환경이 100임을 보장할 수는 없습니다. % 원활하므로 슬레이브 데이터베이스와 마스터 데이터베이스 간의 연결 끊김 문제도 고려해야 합니다.

redis2.8 이전에는 슬레이브 데이터베이스의 연결이 잠시 끊어졌더라도 나중에 슬레이브 데이터베이스가 다시 연결되면 메인 데이터베이스가 직접적으로 무의식적으로 전체 동기화를 수행해야 했습니다. 2.8 이상 버전에서는 증분 복제를 지원하는데, 변경 사항을 저장하기 위한 버퍼가 있어야 하는데, 이 버퍼를 논리적으로 쓰기(Write)라고 합니다. , 처음부터 덮어쓰게 되므로 크기 제한도 있습니다. 슬레이브 라이브러리가 다시 연결되면 슬레이브 라이브러리는 메인 라이브러리에 "현재 xx 위치에 복사했습니다."라고 알립니다. 메인 라이브러리는 슬레이브 라이브러리로부터 메시지를 받은 후 xx 위치의 데이터가 복사되었는지 확인하기 시작합니다. 아직 repl_backlog_buffer에 있다면 xx 이후의 데이터를 슬레이브 라이브러리로 보내면 됩니다. 그렇지 않으면 할 수 있는 일이 없으며 전체 동기화만 다시 수행할 수 있습니다. repl_backlog_buffer

관리자가 필요합니다

마스터-슬레이브 모드에서 메인 데이터베이스가 중단되면 슬레이브 데이터베이스를 메인 데이터베이스로 업그레이드할 수 있지만 이 프로세스는 수동이며 수동 작업에 의존하므로 손실을 줄일 수 없습니다. 최소한 자동 관리 및 선택 메커니즘은 여전히 ​​필요합니다. 이것이

Sentinel입니다. Sentinel 자체도 서비스이지만 모든 데이터를 읽고 쓰는 작업만 담당합니다. Redis 인스턴스는 가끔씩 전송됩니다. 시간은 각 Redis와 통신합니다(Ping 작업). 각 Redis 인스턴스는 지정된 시간 내에 응답하는 한 자신의 위치를 ​​표현할 수 있습니다. 물론, Sentinel 자체가 다운되었거나 네트워크를 사용할 수 없는 경우도 있으므로 일반적으로 Sentinel도 Sentinel 클러스터를 구축하게 되는데, 3개나 5개 등 홀수 개의 클러스터를 갖는 것이 가장 좋습니다. 홀수의 목적은 다음과 같습니다. 주로 선거를 위해 (소수는 다수에 복종합니다).

Ping을 시작한 후 Sentinel이 제 시간에 Pong을 받지 못하면 Redis 인스턴스는 오프라인으로 표시됩니다. 이때는 여전히 오프라인이 아닙니다. 이때 다른 Sentinel도 현재 Sentinel이 오프라인인지 확인합니다. 실제 오프라인에서는 대부분의 센트리가 Redis가 오프라인이라고 판단하면 클러스터에서 쫓아냅니다. 오프라인인 슬레이브 데이터베이스라면 직접 쫓아내면 됩니다. 그렇다면 데이터베이스도 선택을 실행해야 합니다. 선택은 새로운 기본 데이터베이스로 사용하기에 가장 적합한 선택이 아닙니다. 메인 라이브러리로 사용하기에 가장 적합한 라이브러리는 일반적으로 다음 우선순위에 따라 결정됩니다:

  • 가중치 각 슬레이브 라이브러리는 실제로 가중치가 더 높은 슬레이브 라이브러리가 우선순위를 갖습니다. 각 슬레이브 데이터베이스에서 복사 진행 상황이 다를 수 있습니다. 실제로 각 Redis 인스턴스는 위의 조건이 충족되면 고유한 ID를 갖습니다. 그러면 ID가 가장 작은 라이브러리가 메인 라이브러리로 선택됩니다

  • 더욱 강력한 수평 확장성

  • 마스터-슬레이브 모드로 단일 장애 지점 문제를 해결하고, 읽기-쓰기 분리 기술을 통해 애플리케이션이 Sentinel 모드는 자동으로 클러스터를 감독하고 자동 마스터 선택을 실현하며 실패한 노드를 자동으로 제거할 수 있습니다.

    일반적으로 읽기 부담이 증가하는 한 슬레이브 라이브러리를 추가하여 이를 완화할 수 있습니다. 하지만 메인 라이브러리에 대한 부담이 매우 높으면 어떻게 될까요? 이것은 우리가 다음에 이야기할
  • sharding
기술로 이어집니다. 우리는 메인 라이브러리를 여러 조각으로 잘라서 다른 머신에 배포하기만 하면 됩니다. 이 샤딩은 Redis에서의

slots 개념으로, 샤딩 시 Redis는 기본적으로 0~16383으로 나누어 총 16384개의 슬롯을 갖게 되며, 이 슬롯을 각 샤딩 노드에 균등하게 분배하여 로드하는 역할을 한다. 균형. 각 키는 어느 슬롯에 할당되어야 합니까? 가장 중요한 것은 먼저 CRC16을 사용하여 16비트 숫자를 얻은 다음 이 숫자를 모듈로 16384로 사용하는 것입니다.
crc16(key)%16384
로그인 후 복사

然后客户端会缓存槽信息,这样每当一个 key 到来时,只要通过计算就知道该发给哪个实例来处理来了。但是客户端缓存的槽信息并不是一成不变的,比如在增加实例的时候,这时候会导致重新分片,那么原来客户端缓存的信息就会不准确,一般这时候会发生两个常见的错误,严格来说也不是错误,更像一种信息,一个叫做MOVED,一个叫做ASK。moved的意思就说,原来是实例A负责的数据,现在被迁移到了实例B,MOVED 代表的是迁移完成的,但是 ASK 代表的是正在迁移过程中,比如原来是实例A负责的部分数据,现在被迁移到了实例B,剩下的还在等待迁移中,当数据迁移完毕之后 ASK 就会变成 MOVED,然后客户端收到 MOVED 信息之后就会再次更新下本地缓存,这样下次就不会出现这两个错误了。

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

위 내용은 Redis의 다양한 데이터 유형과 클러스터 관련 지식에 대해 이야기해 보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:juejin.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿