우리는 Redis에 문자열, 해시, 목록, 세트, 순서 세트 등 일반적으로 사용되는 여러 데이터 구조가 있다는 것을 항상 알고 있었습니다. 실제로 Redis는 나중에 많은 추가 기능을 추가했는데 그 중 하나는 HyperLogLog이고 다른 하나는 버전 3.2에 추가된 GEO(지리적 위치)였습니다.
HyperLogLog 구조를 간략하게 소개하겠습니다.
먼저 사용법에 대해 이야기하자면, 이 구조는 등록된 IP 수, 일일 방문 IP 수, 페이지의 실시간 UV( PV는 문자열이어야 함), 온라인 사용자 대기 수입니다.
여기서 쓰이는 용도는 모두 xxx 숫자이므로, 계산하려는 수량을 보다 정확하게 추정할 수 있다는 것이 이 데이터 구조의 특징이지만 통계의 자세한 내용을 알 수는 없습니다. 예를 들어, 매일 방문하는 IP 수를 세어보면 그 당시에 방문한 총 IP 수를 알 수 있지만, 이 IP가 무엇인지 알 수 있는 방법은 없습니다.
물론 위에서 언급한 내용을 계산해 봐야 수량을 알 수 있고 모든 세부 목록을 얻을 수 있습니다. 하지만 예를 들어 대규모 웹 사이트의 경우 매일 100만 개의 IP가 있습니다. 대략적으로 계산하면 하나의 IP가 15바이트를 소비하므로 100만 개의 IP는 1,000만 개이면 150M입니다.
HyperLogLog를 다시 살펴보겠습니다. Redis의 각 키는 12K의 콘텐츠를 차지하며 이론적인 저장 공간은 저장된 콘텐츠와 관계없이 대략 2^64 값에 가깝습니다. 12K, 당신은 이 데이터 구조의 역할을 알고 있습니다. 그렇기 때문에 그는 내부의 세부 사항을 알 수 없습니다. 이는 카디널리티 추정 기반의 알고리즘으로 비교적 정확하게 카디널리티만 추정할 수 있으며, 적은 양의 고정 메모리를 사용하여 집합의 고유한 요소를 저장하고 식별할 수 있습니다. 그리고 이 추정치의 기초가 반드시 정확하지는 않습니다. 이는 표준 오차가 0.81%인 근사치입니다.
여기에 더 많은 콘텐츠를 기록할수록 컬렉션에 사용된 콘텐츠와 선명한 대조를 갖기가 더 쉬워집니다. 왜냐하면 HyperLogLog 구조는 범위에서 허용되는 값이 아무리 많아도 회색으로 표시되고 12K의 메모리를 차지합니다.
예를 들어 일일 IP를 기록한다면 매일 1억 개의 IP 접속이 있다고 가정하고 Aggregation을 사용한다면 하루 메모리 사용량은 1.5G가 됩니다. 45G 용량. 하지만 HyperLogLog를 사용하면 하루에 12K, 한 달에 360K입니다. IP의 구체적인 정보를 알 필요가 없는 경우 해당 기록을 메모리에 1년 동안 보관하거나 삭제하지 않을 수 있습니다. 필요한 경우, 당사는 모든 IP 접속 기록을 다른 수단을 통해서도 저장합니다. 일별 정보를 저장하여 월별 총 IP 수(MERGE), 연간 총 IP 수 등을 계산할 수 있습니다(중복 제거).
다음은 HyperLogLog 명령에 대한 소개입니다. 실제로 명령이 적고 목록을 얻을 수 없다는 점을 제외하면 수집 명령과 유사합니다. 또한 이 데이터 구조를 사용하려면 버전 2.8.9 이상이 필요합니다~
PFADD
이 명령을 실행한 후 HyperLogLog의 내부 구조가 업데이트되고 실행되면 피드백이 제공됩니다. 완료 후 HyperLogLog의 내부 카디널리티 추정이 변경되면 1을 반환하고, 그렇지 않으면(이미 존재하는 것으로 간주) 0을 반환합니다.
이 명령의 또 다른 놀라운 특징은 키만 가질 수 있고 값은 가질 수 없다는 것입니다. 즉, 값 없이 빈 키만 생성됩니다.
키가 존재하면 아무것도 하지 않고 0을 반환하고, 존재하지 않으면 생성하고 1을 반환합니다.
이 명령의 시간복잡도는 O(1)이므로 마음껏 사용해 보세요~
명령어 예:
redis> PFADD ip:20160929 "1.1.1.1" "2.2.2.2" "3.3.3.3" (integer) 1 redis> PFADD ip:20160929 "2.2.2.2" "4.4.4.4" "5.5.5.5" # 存在就只加新的 (integer) 1 redis> PFCOUNT ip:20160929 # 元素估计数量没有变化 (integer) 5 redis> PFADD ip:20160929 "2.2.2.2" # 存在就不会增加 (integer) 0
실제로 우리는 꽤 정확해요, 하하.
PFCOUNT
실제로 위의 연구에서 이미 이것을 사용해 본 적이 있는데 여기서 소개하겠습니다.
명령이 단일 키에 적용될 때 키의 카디널리티 추정치를 반환합니다. 키가 존재하지 않으면 0이 반환됩니다.
여러 키에 적용하면 해당 키의 통합 추정값을 반환합니다. 이러한 키를 병합하는 것과 유사하게 이 명령을 호출하여 출력합니다.
이 명령이 단일 값에 대해 작동할 때 시간 복잡도는 O(1)이고 N 값에 대해 작동할 때 시간 복잡도는 O(N )입니다. 이 명령의 복잡성은 낮아질 것입니다.
명령 예:
redis> PFADD ip:20160929 "1.1.1.1" "2.2.2.2" "3.3.3.3" (integer) 1 redis> PFCOUNT ip:20160929 (integer) 3 redis> PFADD ip:20160928 "1.1.1.1" "4.4.4.4" "5.5.5.5" (integer) 1 redis> PFCOUNT ip:20160928 ip:20160929 (integer) 5
PFMERGE
여러 HyperLogLog를 하나의 HyperLogLog로 병합합니다. 실제로 이는 이해하기 쉽고 결합된 추정 카디널리티도 모든 HyperLogLog 추정 카디널리티의 합집합과 유사합니다.
이 명령의 첫 번째 매개변수는 대상 키이고 나머지 매개변수는 병합할 HyperLogLog입니다. 명령 실행 시 대상 키가 존재하지 않으면 생성 후 병합됩니다.
이 명령의 시간 복잡도는 O(N)입니다. 여기서 N은 병합할 HyperLogLog 수입니다. 그러나 이 명령의 지속적인 시간 복잡도는 상대적으로 높습니다.
명령어 예:
edis> PFADD ip:20160929 "1.1.1.1" "2.2.2.2" "3.3.3.3" (integer) 1 redis> PFADD ip:20160928 "1.1.1.1" "4.4.4.4" "5.5.5.5" (integer) 1 redis> PFMERGE ip:201609 ip:20160928 ip:20160929 OK redis> PFCOUNT ip:201609 (integer) 5
到此HyperLogLog所有的命令就都介绍完了,没错,目前就只有这三个。其实也很简单的,知道了这个结构的用法,也就知道什么时候适合用了,对我们非常珍贵的内存还是很有帮助。