레디 스에 원칙 HyperLogLog 알고리즘이 그것을 사용하는 방법 :십시오

에서 :  https://www.cnblogs.com/linguanh/p/10460421.html

디렉토리

  • 질문 프로토 타입
  • 조건 선택
  • HyperLogLog
  • 베르누이 시행
  • 예상 최적화
  • 뭔가해야 할 일
    • 비트 문자열
    • 포인트 배럴
    • 통신
  • HyperLogLog의 응용 프로그램에서 레디 스
    • 레디 스의 HyperLogLog 원리
  • 드리프트 보정
  • 거인의 어깨

질문 프로토 타입

당신은 이러한 기능을 구현하려면 :

있는 페이지 통계 APP 또는 웹 페이지는 사용자가 매일 입력합니다 얼마나 많은 수 있습니다. 동일한 사용자가 반복적으로 한 번 입력을 클릭 함.

스마트 즉시 사용의 생각  HashMap 이 될 수있는이 데이터 구조를,뿐만 아니라 디엠 퍼시스를 충족 할 수 있습니다. 사실, 이것은 다른 솔루션들 사이에서 솔루션입니다.

문제가 어려운 것은 아니지만, 그러나 변수에 참여는 일정 크기에 도달 한 후 간단한 질문이 문제가 될 것입니다. APP는 도달 니 카츠 사용자를 가정 百万또는 千万以上级别우리가 채택 할 경우  HashMap 관행, 프로그램이 메모리를 많이 차지 이어질 것입니다.

여기에서 우리는에서 추정하려고  HashMap 메모리 풋 프린트의 문제를 해결하는 시간. 정의 가정 HashMap 에  Key 는 AS  string 유형 value 의  bool. key 사용자에 해당하는 Id, value그것은이다 是否点击进入. 물론, 경우 다른 사용자의 액세스 시간의 수백만. HashMap 메모리 공간은 다음과 같습니다 100万 * (string + bool).

조건 선택

현재 솔루션을 기존의 상술 한 문제를, 말할 수 HashMap 는 최대 규모의 메모리 공간 중 하나입니다. 통계가 많이없는 경우, 당신은 문제를 해결하기 위해이 방법을 사용할 수 있습니다, 또한 달성 간단하다.

또한 B+ 树, Bitmap 位图이 문서는 소개  HyperLogLog알고리즘 솔루션을.

특정 조건이 허락하에 통계 에러율 천만 뷰를 허용하는 이런 이만 이하의 최종 통계, 허용 범위 내에서 많은 양의 데이터를 허용하기 전에 채용 할 수있는 경우, HyperLogLog알고리즘을 상기 카운트를 해결 유사한 문제.

HyperLogLog

HyperLogLog이하에서는라고도 HLL그것이  LogLog 알고리즘의 업그레이드 된 버전이 부정확 중량 계수를 제공하는 것이다. 다음과 같은 기능 :

  • 코드는 달성하기 어렵습니다.
  • 통계 데이터 메모리에, 약간의 엄청난 금액을 사용할 수 있도록  Redis 구현  HyperLogLog12K메모리는 통계가 될 수 2^64데이터입니다.
  • 특정 오류 수는 전체 오류 비율이 낮습니다. 0.81 %의 표준 오류입니다.
  • 오류가 설정 될 수 있습니다 辅助计算因子감소시킬 수 있습니다.

기본 데이터 형 메모리 풋 프린트에서 약간의 프로그램은 학생들의 이해를 가지고, 당신은 단지 필요합니다 12K메모리 셀 수 2^64데이터를 놀라게했다. 당신이 말하는 이유는 무엇입니까,의 다음 예제를 제공하자 :

가라  Java 일반적 언어 long= 8 비트 1 바이트, 즉 : 바이트, 즉 8 비트이고, 8 바이트를 사용 long가능한 데이터 유형의 최대 개수로 표현된다 2^63-1. 위의에 해당 2^64이 있다고 가정 수 2^63-1에서, 많은 숫자  0 ~ 2^63-1, 따라 long1k = 1024字节메모리의 총량을 계산하는 규칙이 있습니다 : ((2^63-1) * 8/1024)K그것은 훨씬 더 많은 저장 공간보다, 매우 많은 수입니다 12K. 그리고  HyperLogLog 당신은 수있는  12K 통계를 완료 할 수 있습니다.

베르누이 시행

왜 이해를 HyperLogLog먼저 이해에서, 통계의 거대한 양의 매우 작은 데이터 메모리를 사용하기 전에 伯努利试验.

伯努利试验수학은 概率论이 이야기에서 유래이다, 내용의 일부 抛硬币.

코인은 양극과 음극을 모두 가지고 드로의 앞에 남중 떨어져 위로 확률 50 %있다. 그것은 지금까지 긍정적, 우리는 전체 재판으로 기록 나타날 때까지 가정은 항상 긍정적 인 표시 네 번 던질 수, 간 나타난 긍정적를 던질 수 있습니다, 동전 뒤집기있다. 여러 번만큼 긍정적이 있었다으로, 던지는 방법에 상관없이, 그것은 실험으로 기록됩니다. 이 테스트입니다 伯努利试验.

그래서 많은 시간에 伯努利试验이 가설에 대한 여러 번 n번. 그것은이었다가 있다는 것을 의미 n배 긍정적. 각 가정하면 伯努利试验여러 번 던질 경험 k. 우선 伯努利试验, 수 설정된 k1제 있도록 n시간에 대응 kn.

그 중,이에 대한 n시간을 伯努利试验던졌습니다, 우리는 확실히 최대 수있을 것이다 k12 시간 후 우리는이 전화를 긍정적 인 표시 던지고, 예를 들어, k_max토스의 가장 높은 숫자 대신.

伯努利试验쉬운 다음과 같은 결론을 도출하기 :

  1. N 토스 베르누이 프로세스 k_max의 수보다 더 크다.
  2. 베르누이 프로세스 N 번, 적어도 한번 던지고 k_max들의 수와 동일

최대 우도 추정의 최종 접합 방법은, 그것이 발견 된 nk_max관계를 추정하는 존재 : n = 2^(k_max) . 이 로컬 방식으로 정보의 기본적인 이해 우리가 전체 데이터 흐름 특성을 추정 이상 보일 수는 도출하고 확률 통계의 방법에 의해이 관계를 테스트 할 필요가있다.

예를 들어, 다음과 같이 :

第一次试验: 抛了3次才出现正面,此时 k=3,n=1
第二次试验: 抛了2次才出现正面,此时 k=2,n=2
第三次试验: 抛了6次才出现正面,此时 k=6,n=3
第n 次试验:抛了12次才出现正面,此时我们估算, n = 2^12

위의 예에서 실험군의 수가 3 개 그룹의 총 후 k_max = 6, 최종 N = 3 가정, 우리는 크게, 추정 식에 들어가는 3 ≠ 2 ^ 6. 이 추정 방법의 오차가 큰 경우 실험의 수가 작은 경우 즉,이다.

예상 최적화

예를 들어 위의 세 그룹에서, 우리는 추정했다. 하나의 둥근 경우, n이 큰 충분 다음 때, 추정 오류율은 여전히 ​​작은 충분하지 감소하지만됩니다.

그것은 여러 라운드를 수행 할 수 있습니까? 예를 들어, 100 개 이상의 시험의 라운드, 다음은 각 라운드를 k_max 가지고, 다음 즉, 평균을 복용 :  k_mx/100. 그런 다음 최종 추정 N. 여기서 인 LogLog추정 공식은 :

상기 화학식 DVLL것과 대응 n, constant보정 계수, 및 특정 값의 불확실성은, 브랜치는 실제 상황에 따라 설정 될 수있다. m이 시험 라운드의 수를 나타냅니다. 에 십자가와 헤드 R평균 : (k_max_1 + ... + k_max_m)/m.

이 테스트 라운드를 증가 시키면, 다음 걸릴 k_max알고리즘의 평균 최적화 LogLog방법을. 그리고  HyperLogLogLogLog의 차이는 그렇지 사용한다는 것입니다 平均数,하지만 调和平均数. 调和平均数보다 平均数장점 큰 충격 값이 쉽지 않다. 다음은 예입니다 :

임금을 평균 :

A는 B에 1,000 / 월 30,000 / 월입니다 평균 방법을 사용하다 : (30000 + 1000) / 2 = 15500

조화 평균에 의해 인 2 / (+ 1/1000 1/30000) ≈ 1935.484

물론, 调和平均数平均数효과가 더 좋을 것입니다. 다음은 인 调和平均数계산의 방법,  요약 기호.

뭔가해야 할 일

우리가 이미 알고보다도, 동전 던지기의 예에서, 베르누이 재판의 출현은 수 k_max를 추정 할 n.

그렇다면이 추정 방법 및 다음과 같은 문제는 그것과 관련이있다?

있는 페이지 통계 APP 또는 웹 페이지는 사용자가 매일 입력합니다 얼마나 많은 수 있습니다. 동일한 사용자가 반복적으로 1 회 기록 맞을

HyperLogLog나는 일을하고 있습니다. 입력 데이터의 다음 단계는 :

1. 비트 문자열

으로 hash기능, 데이터가 변환되고, 比特串차례로, 예를 들어, 5 입력 : 101. 왜 변환해야합니까?

동전 던지기 및 서신으로 인해 比特串최종 데이터가 변환되면 0 포지티브 네거티브 1이고,  10010000볼 로우에서 하이, 후 오른쪽에서 왼쪽으로, 우리 때 처음 1, 말할 수 그것은 긍정적이다.

그래서 위의 추정 결론에 따라, 우리가 할 수있는 최대의 수를 실험의 수의 합계를 추정하는 실험 토스 동전의 앞을 던져 수 있으며, 같은가에 저장된 데이터를 기반으로합니다 그들의 가장 큰 일을 변환 k_max 위치가 저장되는 데이터의 양을 추정한다.

2. 포인트 배럴

얼마나 많은 포인트 버킷 휠을 구분됩니다. 저장소에 컴퓨터 추상, 비트 ( '비트) 단위로 저장되고, 길이 L (S)의 큰 배열이 S 동등이 그룹 m 기, m 관심들로 분할되고, 숫자는 각각이 대응하는 휠이며 손잡이의 비트들의 평균 개수를 P.이며 쉬운 다음과 같은 관계를 그리려면

  • L = S.length
  • L = 선택된 M과 P *
  • K에서 S 메모리 점유 = L / 1,024분의 8

에서는  Redis 제 1, HyperLogLog설정 : m = 16,834, p = 6 , L = 16,834 * 6. 점유에 메모리 = 16834 * 1024년 6월 8일 = 12K

같은 시각 :

0组     第1组                       .... 第16833组
[000 000] [000 000] [000 000] [000 000] .... [000 000]

3. 대응

이제 다시 우리의 원래 질문 APP 페이지의 사용자 통계로 이동합니다.

  • APP는 설정 홈 키는 다음 주
  • 사용자 ID는 다음과 같습니다 IDN, N-> 0, 1, 2, 3 ....

이 문제에 통계적으로 상이한 사용자 ID를 식별하는 사용자는, 우리는 같은 사용자 ID를 넣을 수 hash입력. 즉 :

해시 (ID) = 비트 열

다른 사용자 ID는 필연적으로 다른 것입니다 比特串. 각각은 比特串, 위치 한 번도 최소한에 바인딩됩니다. 우리의 비유의 각 比特串한 번 伯努利试验.

이제 分轮, 즉 分桶. 우리는 서로를 설정할 수 있습니다 그래서 比特串얼마나 많은 소수에 비트 배럴에있는 레이블 값에 해당한다 전에. 가정 比特串사용자 ID가 존재하는 경우, 하부 두 비트하는 마커 배럴을 계산하는데 사용된다 比特串1,001,011,000,011 :이다. 그것은 여기서 첨자 욕조 : 11(2) = 1*2^1 + 1*2^0 = 3첫 번째 세 번째 배럴, 즉,이다.

위의 예에서, 상기 터브의 계산 된 수 및 나머지 比特串인 : 10,010,110,000 로우에서 하이로 참조 (1)의 첫번째 발생의 위치는 5이다. 즉, 경우에 제 배럴 처음 세 시험 k_max = 5. 도 5는 대응하는 이진 : 101, 각 비트는 P-욕조 때문이다. 이 P> = 3 (101)에 저장 될 수있는 경우.

상기 과정을 모방 다른 사용자 ID의 복수, 그것은 상이한 버킷 분산 각 버킷은 k_max를 갖는다. 당신이 계산 할 때 그리고  mian 사용자의 수를 하나의 추정치가있는 경우 페이지에 맞았습니다. , 추정 식을 대체 추정치를 제공 할 수있을 것입니다 k_max 모든 버킷의 최종 조합.

다음은 인  HyperLogLog 변수 및 의역의 조화 평균 추정 식의 조합 LogLog같은 것의을 :

HyperLogLog의 응용 프로그램에서 레디 스

첫째, 레디 스에서, HyperLogLog는 고급 데이터 구조 중 하나입니다. 이 명령은 다음을 포함하여 제공하지만, 이에 국한되지 않습니다 :

  • pfadd 키 값에 대응 저장된 키값
  • pfcount 키 값의 수의 주요 통계

리콜 원래 APP 통계 페이지에서 사용자의 문제가. 키가 페이지 이름에 해당하는 경우, 값은 사용자 ID에 해당. 대응에 문제 다음 바로.

레디 스의 HyperLogLog 원리

前面我们已经认识到,它的实现中,设有 16384 个桶,即:2^14 = 16384,每个桶有 6 位,每个桶可以表达的最大数字是:2^5+2^4+...+1 = 63 ,二进制为: 111 111 。

对于命令:pfadd key value

在存入时,value 会被 hash 成 64 位,即 64 bit 的比特字符串,前 14 位用来选择这个 value 的比特串中从右往左第一个 1 出现的下标位置数值要存到那个桶中去,即前 14 位用来分桶。设第一个1出现位置的数值为 index 。当 index=5 时,就是: ....10000 [01 0000 0000 0000]

之所以选 14位 来表达桶编号是因为,分了 16384 个桶,而 2^14 = 16384,刚好地,最大的时候可以把桶利用完,不造成浪费。假设一个字符串的前 14 位是:00 0000 0000 0010 (从右往左看) ,其十进制值为 2。那么 index 将会被转化后放到编号为 2 的桶。

index 的转化规则:

首先因为完整的 value 比特字符串是 64 位形式,减去 14 后,剩下 50 位,那么极端情况,出现 1 的位置,是在第 50 位,即位置是 50。此时 index = 50。此时先将 index 转为 2 进制,它是:110010 。

因为16384 个桶中,每个桶是 6 bit 组成的。刚好 110010 就被设置到了第 2 号桶中去了。请注意,50 已经是最坏的情况,且它都被容纳进去了。那么其他的不用想也肯定能被容纳进去。

因为 fpadd 的 key 可以设置多个 value。例如下面的例子:

pfadd lgh golang
pfadd lgh python
pfadd lgh java

根据上面的做法,不同的 value,会被设置到不同桶中去,如果出现了在同一个桶的,即前 14 位值是一样的,但是后面出现 1 的位置不一样。那么比较原来的 index 是否比新 index 大。是,则替换。否,则不变。

最终地,一个 key 所对应的 16384 个桶都设置了很多的 value 了,每个桶有一个k_max。此时调用 pfcount 时,按照前面介绍的估算方式,便可以计算出 key 的设置了多少次 value,也就是统计值。

value 被转为 64 位的比特串,最终被按照上面的做法记录到每个桶中去。64 位转为十进制就是:2^64,HyperLogLog 仅用了:16384 * 6 /8 / 1024 K 存储空间就能统计多达 2^64 个数。

偏差修正

在估算的计算公式中,constant 变量不是一个定值,它会根据实际情况而被分支设置,例如下面的样子。

假设:m为分桶数,p是m的以2为底的对数。

// m 为桶数
switch (p) {
   case 4:
       constant = 0.673 * m * m; case 5: constant = 0.697 * m * m; case 6: constant = 0.709 * m * m; default: constant = (0.7213 / (1 + 1.079 / m)) * m * m; }

巨人的肩膀

由简单的抛硬币试验可以引导出如此的震撼的算法,数学之强大。

感谢下面两遍博文的指引:

本文所有图片来源于:

https://www.jianshu.com/p/55defda6dcd2

本文内容参考于:

http://www.rainybowe.com/blog/2017/07/13/%E7%A5%9E%E5%A5%87%E7%9A%84HyperLogLog%E7%AE%97%E6%B3%95/index.html

手动直观观察 LogLog 和 HyperLogLog 变化的网站:

http://content.research.neustar.biz/blog/hll.html

추천

출처www.cnblogs.com/liuqingsha3/p/11958801.html