思路,搞一個(gè)集合,將當(dāng)天登陸過(guò)的用戶的id,存起來(lái),用于統(tǒng)計(jì)日活;
目前,用Redis統(tǒng)計(jì)日活的方案有3種:
1.使用set集合;
2.使用bitset;
3.使用hyperLogLog;
第一種方案使用set,這種方案不推薦,因?yàn)樵趕et里面存一個(gè)用戶id,就要使用32bit,1億用戶每天就要存3200M。
第二種方案:
先看代碼:
public String SimpleBitset(){
DateTime dt = new DateTime();
String strDate = dt.toString("yyyyMMdd");
RBitSet set = redisson.getBitSet("log_"+dt.toString("yyyyMMdd"));
set.set(0L,true);
set.set(1L,true);
// 如果一下子加到4294967295,那么在redis這個(gè)鍵就會(huì)達(dá)到500多MB
// 所以如果用戶數(shù)在百萬(wàn)基本,可以用這種方式,而如果用戶數(shù)過(guò)億了,會(huì)比較消耗內(nèi)存
// 如果linux判斷redis是個(gè)危害,會(huì)把它干掉
// set.set(4294967295L,true);
// 超過(guò)4294967295L就會(huì)報(bào)錯(cuò)
// set.set(4294967296L,true);
// 查詢有多少DAU
System.out.println(set.cardinality());
return "";
}
用這種方式,有一定限制條件:
1.用戶數(shù)不能超過(guò)4294967296(基本也沒(méi)幾個(gè)超得過(guò)的吧);
2.它占用的內(nèi)存大小,不在于存了多少,而在于最大的那個(gè)id是多少,比如今天第一個(gè)訪問(wèn)的id是100000000,那么這個(gè)key的占用內(nèi)存就會(huì)是12M左右(1億個(gè)bit);
如果用戶數(shù)量也就1億左右,可以考慮這種方式。
第三種方案:
先看代碼:
public String HyperLogLog(){
RHyperLogLog<Long> log = redisson.getHyperLogLog("log");
log.add(1L);
log.add(2L);
log.add(3L);
log.add(3L);
log.add(3L);
log.add(3L);
log.add(3L);
log.add(3L);
log.add(3L);
log.add(3L);
log.add(10000000L);
// 得到的結(jié)果是4
System.out.println(log.count());
return "";
}
1.它統(tǒng)計(jì)1億用戶,大概要1M多點(diǎn);
2.HyperLogLog的統(tǒng)計(jì)結(jié)果并不是一個(gè)精確的值,誤差在0.81%左右,但是對(duì)于統(tǒng)計(jì)用戶數(shù)這種場(chǎng)景來(lái)說(shuō)足夠了。