Redis 큰 key 다 중 key 분할 실현 방법 분석

배경
업무 장면 에서 각종 큰 key 다 key 의 상황 이 자주 발생 한다.예 를 들 어:
1:하나의 간단 한 key 에 저 장 된 value 가 매우 크다.
2:hash,set,zset,list 에 너무 많은 요 소 를 저장 합 니 다(만 단위)
3:하나의 클 러 스 터 는 억 대의 key 를 저장 하고 Key 자체 가 너무 많 으 면 더 많은 공간 을 차지 할 수 있 습 니 다.
(예 를 들 어 의외 가 없 으 면 글 에서 언급 한 hash,set 등 데이터 구 조 는 모두 redis 중의 데이터 구 조 를 가리킨다)
redis 는 단일 스 레 드 로 실행 되 기 때문에 한 번 에 조작 하 는 value 가 전체 redis 의 응답 시간 에 부정적인 영향 을 미 칠 수 있 기 때문에 업무 상 뜯 을 수 있 으 면 뜯 고 다음은 전형 적 인 분리 방안 을 들 겠 습 니 다.
하나,하나의 간단 한 key 저장 의 value 가 매우 크다.
i:이 대상 은 매번 액세스 해 야 합 니 다.
대상 을 몇 개의 key-value 로 나 누 어 multiGet 을 사용 하여 값 을 얻 으 려 고 시도 할 수 있 습 니 다.이러한 분 리 는 한 번 의 조작 압력 을 나 누 어 여러 개의 redis 인 스 턴 스 에 할당 하여 하나의 redis 에 대한 IO 영향 을 낮 추 는 데 의미 가 있 습 니 다.
ii:이 대상 은 매번 일부 데이터 만 액세스 해 야 합 니 다.
첫 번 째 방법 처럼 몇 개의 key-value 로 나 눌 수도 있 고 이것 을 하나의 hash 에 저장 할 수도 있 습 니 다.각 field 는 구체 적 인 속성 을 대표 합 니 다.
hget,hmget 을 사용 하여 부분의 value 를 가 져 오고 hset,hmset 를 사용 하여 일부 속성 을 업데이트 합 니 다.
2.value 에 너무 많은 요 소 를 저장 합 니 다.
장면 과 유사 한 첫 번 째 방법 으로 이런 요 소 를 분리 할 수 있다.
hash 를 예 로 들 면 원래 의 정상 적 인 액세스 프로 세 스 는 hget(hashkey,field)입 니 다.hset(hashKey, field, value)
현재 하나의 통 의 수량 을 고정 합 니 다.예 를 들 어 10000,매번 액세스 할 때마다 로 컬 에서 field 의 hash 값 을 계산 하고 10000 을 모드 로 나 누 어 이 field 가 어느 key 에 떨 어 졌 는 지 확인 합 니 다.
new Hashkey=hashkey+(set,zset,list 도 상기 방법 과 유사 할 수 있 습 니 다.
그러나 일부 적합 하지 않 은 장면 이 있 습 니 다.예 를 들 어 lpop 의 데 이 터 는 최초 로 push 가 list 에 들 어 갔 음 을 확보 하려 면 추가 적 인 속성 이 필요 하거나 key 의 조합 에서 일 을 해 야 합 니 다(예 를 들 어 list 는 시간 에 따라 분 리 됩 니 다).
3.한 군집 에 억 대의 key 를 저장 했다.
키 의 개수 가 너무 많 으 면 더 많은 메모리 공간 을 차지 할 수 있 습 니 다.
i:key 자체 의 점용(키 마다 카 테 고리 접두사 가 있 습 니 다)
ii:클 러 스 터 모드 에서 서버 는 slot2key 의 맵 관 계 를 구축 해 야 합 니 다.그 중의 지침 은 key 가 많은 상황 에서 도 커 다란 공간 을 낭비 합 니 다.
이 두 가지 측면 에서 key 개 수 억 에 달 할 때 메모리 소모 가 매우 뚜렷 하 다(Redis 3.2 와 다음 버 전 은 모두 이 문제 가 존재 하고 4.0 이 최적화 되 었 다).
그래서 key 의 개 수 를 줄 이면 메모리 소 모 를 줄 일 수 있 습 니 다.참고 할 수 있 는 방안 은 Hash 구조 저장 소 를 바 꾸 는 것 입 니 다.즉,원래 Redis String 의 구조 저장 소 를 직접 사 용 했 는데 지금 은 여러 key 를 하나의 Hash 구조 에 저장 하고 구체 적 인 장면 은 다음 과 같 습 니 다.
1:key 자체 가 매우 강 한 관련 성 을 가진다.예 를 들 어 여러 key 는 하나의 대상 을 대표 하고 모든 key 는 대상 의 속성 이다.이런 것 은 특정한 대상 의 특징 에 따라 새로운 Key―Hash 구 조 를 설정 할 수 있 고 원래 의 key 는 이 새로운 Hash 의 field 로 할 수 있다.
예 를 들 어 설명:
원래 저 장 된 키 세 개
user.zhangsan-id = 123;
user.zhangsan-age = 18;
user.zhangsan-country = china;
이 세 개의 key 자체 가 매우 강 한 관련 특성 을 가지 고 있 으 며,Hash 메모리 로 전환 합 니 다.이렇게 key=user.zhangsan
field:id = 123;
field:age = 18;
field:country = china;
즉,redis 에 저 장 된 것 은 key:user.zhangsan 입 니 다.그 는 세 개의 field 가 있 고 모든 field+key 는 원래 의 key 에 대응 합 니 다.
2:key 자체 가 관련 성 이 없 으 므 로 전체 수량 을 예측 하고 상기 두 번 째 장면 과 유사 한 방안 을 취해 고정된 통 수량 을 미리 나눈다.
예 를 들 어 현재 key 의 총 수 를 2 억 으로 예상 하고 하나의 hash 에 100 개의 field 를 저장 하 는 것 으로 계산 하면 2 억/100=200 W 통(200 W 개의 key 가 차지 하 는 공간 이 적 고 2 억 은 20G 에 가 까 울 수 있다)이 필요 하 다.
원래 예 를 들 어 세 개의 키 가 있 었 다.
user.123456789
user.987654321
user.678912345
현재 200 W 고정 통분 에 따라 먼저 통 의 번호 hash(123456789)%200 W 를 계산 하 는 것 입 니 다.여기 서 이 hash 알고리즘 의 값 이 정수 임 을 보증 하 는 것 이 좋 습 니 다.그렇지 않 으 면 다음 모드 의 규칙 을 조정 해 야 합 니 다.
이렇게 세 개의 키 를 계산 해 낸 통 은 각각 1,2,2 이다.그래서 저장 할 때 API hset(key,field,value)을 호출 하고 읽 을 때 hget(key,field)을 사용 합 니 다.

두 곳 을 주의 하 십시오.1.hash 취 모 는 음수 에 대한 처리 입 니 다.2.미리 통 을 나 눌 때 하나의 hash 에 저 장 된 값 은 512 를 초과 하지 않 는 것 이 좋 습 니 다.100 정도 가 적당 합 니 다.
4.큰 Bitmap 또는 부 릉 필터(Bloom)분할
bitmap 나 부 릉 필 터 를 사용 하 는 장면 은 데이터 양 이 많은 경우 가 많 습 니 다.이런 상황 에서 Bitmap 와 부 릉 필 터 는 사용 공간 도 비교적 큽 니 다.예 를 들 어 회사 userid 에 맞 는 부 릉 필 터 는 512 MB 의 크기 가 필요 합 니 다.이것 은 redis 에 있어 절대적 인 큰 value 입 니 다.
이런 장면 에서 우 리 는 이 를 충분히 작은 비트 맵 으로 나 누 어야 한다.예 를 들 어 512 MB 의 큰 비트 맵 을 1024 개의 512 KB 의 비트 맵 으로 나 누 는 것 이다.그러나 분할 할 때 는 키 를 하나씩 비트 맵 에 두 는 것 에 주의해 야 한다.일부 업 무 는 Bitmap 만 뜯 지만 하나의 전체적인 bitmap 으로 보기 때문에 하나의 key 는 여러 개의 Bitmap 에 떨 어 집 니 다.그러면 하나의 key 가 여러 노드,여러 개의 Bitmap 를 조회 해 야 할 수도 있 습 니 다.
다음 그림 에서 요 청 된 값 은 hash 에 의 해 여러 Bitmap 에 있 습 니 다.즉,redis 의 여러 key 에 있 습 니 다.이 key 들 은 서로 다른 노드 에 있 을 수 있 습 니 다.이렇게 나 누 면 조회 의 효율 을 크게 낮 출 수 있 습 니 다.

따라서 우리 가 해 야 할 일 은 모든 분 리 된 비트 맵 을 독립 된 비트 맵 으로 간주 한 다음 에 hash 를 통 해 서로 다른 키 를 서로 다른 비트 맵 에 분배 하 는 것 이지 모든 작은 비트 맵 을 하나의 전체 로 간주 하 는 것 이 아니다.이렇게 한 후 매번 요청 할 때마다 redis 의 key 하나만 가 져 오 면 됩 니 다.

이 를 통 해 쪼 개 면 비트 맵 이 작 아진 셈 인 데,부 릉 필터 오 판 율 이 높 아 지 는 것 아니 냐 는 학생 들 의 질문 이 있 을 수 있다.실제로는 그렇지 않 습 니 다.부 릉 필터 의 오 판 률 은 해시 함수 개수 k,집합 원소 개수 n,그리고 Bitmap 크기 m 가 결정 한 것 입 니 다.

따라서 우리 가 첫 번 째 단계,즉 키 를 서로 다른 비트 맵 에 분배 할 때 가능 한 한 고 르 게 나 눌 수 있다 면 n/m 의 값 은 거의 같 고 오심 율 도 변 하지 않 을 것 이다.구체 적 인 오 판 률 추론 은 wiki:Bloom 을 참고 할 수 있 습 니 다.filter
또한 클 라 이언 트 도 편리 한 api(>=2.3.4 버 전)를 제공 합 니 다.setBits/getBits 는 같은 key 의 여러 bit 값 을 한 번 에 조작 하 는 데 사 용 됩 니 다.
권장:k 는 13 개,단일 Bloomfilter 는 512 KB 이하 로 제어 합 니 다.
이상 의 방안 은 참고 로 제공 되 며,여러분 이 기타 우수한 방안 을 제공 하 시 는 것 을 환영 합 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기