網站天天有1億的訪問量,產品提出要統計每一個uid的周活躍,目前是日誌分析解決的,天天有20G的日誌,公司有dip平臺會用日誌去計算,每次要計算兩小時才能處理完。redis
考慮了一下是否能夠用redis的bitmap的方式來作一個統計周活躍的功能數組
先簡單說下bitmap的原理: 假設有3個同窗:bash
小明 1 | 小明 2 | 小明 3 |
---|---|---|
女 | 女 | 女 |
若是有三間房,0是男,女是1,網站
房1 | 房2 | 房2 |
---|---|---|
0 | 1 | 1 |
若是要統計如今班上有幾位女生,就能夠看到兩個1就是兩位女生ui
在計算機裏,一個字節裏有8個二進制位,即1byte=8bit 假設有7個數字,咱們能夠按照編號放進一段連續內存裏,對應位置中存在就顯示1,其它默認都顯示0 好比 3,5,1,7,11,15,4,1 那對應的位置爲:spa
byte0 0 1 0 1 0 1 0 1
byte1 0 0 0 1 0 0 0 1
複製代碼
很明顯咱們已經方便的對這些數字作了排序了,甚至還作了排重 若是咱們要找7是否存在這個數組中,日誌
只須要7/8 對應到第一個字節byte0中
7%8對應到第7位上,若是是1就存在,0就不存在。
複製代碼
若是兩億的數字作排序排重,咱們大概要佔用好幾G的空間,若是用bitmap方式,最少只須要200000000/8/1024/1024 = 24M的空間就夠了code
假設這是咱們uid的登陸狀況 0表明未登陸,1表明登陸對象
Monday
8987129 0
8298191 1
8892198 1
Tuesday
8987129 0
8298191 0
8892198 1
Wednesday
8987129 1
8298191 1
8892198 1
Thursday
8987129 0
8298191 0
8892198 0
Friday
8987129 0
8298191 1
8892198 1
Saturday
8987129 0
8298191 1
8892198 0
Sunday
8987129 1
8298191 1
8892198 0
複製代碼
用setbit方法,將這些數據錄入到redis中:排序
setbit key offset value
設置offset對應二進制上的值,返回該位上的舊值
注意:若是offset過大,則會在中間填充0
   offset最大到2^32-1,便可推出最大的字符串爲512M
複製代碼
127.0.0.1:6379> setbit Monday 8987129 0
(integer) 0
127.0.0.1:6379> setbit Monday 8298191 1
(integer) 0
127.0.0.1:6379> setbit Monday 8892198 1
(integer) 0
127.0.0.1:6379> setbit Tuesday 8987129 0
(integer) 0
127.0.0.1:6379> setbit Tuesday 8298191 0
(integer) 0
127.0.0.1:6379> setbit Tuesday 8892198 1
(integer) 0
127.0.0.1:6379> setbit Wednesday 8987129 0
(integer) 0
127.0.0.1:6379> setbit Wednesday 8298191 1
(integer) 0
127.0.0.1:6379> setbit Wednesday 8892198 1
(integer) 0
127.0.0.1:6379> setbit Thursday 8987129 0
(integer) 0
127.0.0.1:6379> setbit Thursday 8298191 0
(integer) 0
127.0.0.1:6379> setbit Thursday 8892198 0
(integer) 0
127.0.0.1:6379> setbit Friday 8987129 0
(integer) 0
127.0.0.1:6379> setbit Friday 8298191 1
(integer) 0
127.0.0.1:6379> setbit Friday 8892198 1
(integer) 0
127.0.0.1:6379> setbit Saturday 8987129 0
(integer) 0
127.0.0.1:6379> setbit Saturday 8298191 1
(integer) 0
127.0.0.1:6379> setbit Saturday 8892198 0
(integer) 0
127.0.0.1:6379> setbit Sunday 8987129 0
(integer) 0
127.0.0.1:6379> setbit Sunday 8298191 1
(integer) 0
127.0.0.1:6379> setbit Sunday 8892198 0
(integer) 0
複製代碼
接下來要計算7天內有登陸行爲的用戶,只須要將週一到週五的值作位或運算就能夠了
按位與運算符(&)
參加運算的兩個數據,按二進制位進行「與」運算。
運算規則:0&0=0; 0&1=0; 1&0=0; 1&1=1;
即:兩位同時爲「1」,結果才爲「1」,不然爲0
按位或運算符(|)
參加運算的兩個對象,按二進制位進行「或」運算。
運算規則:0|0=0; 0|1=1; 1|0=1; 1|1=1;
即 :參加運算的兩個對象只要有一個爲1,其值爲1。
異或運算符(^)
參加運算的兩個數據,按二進制位進行「異或」運算。
運算規則:0^0=0; 0^1=1; 1^0=1; 1^1=0;
即:參加運算的兩個對象,若是兩個相應位爲「異」(值不一樣),則該位結果爲1,不然爲0。
複製代碼
最後計算7天內登陸過的活躍用戶:
127.0.0.1:6379> bitop OR result Monday Tuesday Wednesday Thursday Friday Saturday Sunday
複製代碼
bitop operation rs key1 [key2..]
對key1 key2作opecation並將結果保存在rs上
opecation能夠是AND(與) OR(或) NOT(非) XOR(異或)
複製代碼
這裏計算的結果假設3個uid都是連續的話就是 110,其實多是 ...1.....1....0...... 也就是本週有兩個活躍用戶登陸過。
就這樣,一個上億訪問量的日誌統計,在redis的bitmap方式輕鬆解決。