很多**都提供了簽到功能(這裡不考慮資料落地事宜),並且需要展示最近乙個月的簽到情況,如果使用bitmap我們怎麼做?一言不合亮**!
<?php
$redis = new redis();
$redis->connect('127.0.0.1');
//使用者uid
$uid = 1;
//記錄有uid的key
$cachekey = sprintf("sign_%d", $uid);
//開始有簽到功能的日期
$startdate = '2017-01-01';
//今天的日期
$todaydate = '2017-01-21';
//計算offset
$starttime = strtotime($startdate);
$todaytime = strtotime($todaydate);
$offset = floor(($todaytime - $starttime) / 86400);
echo "今天是第天" . php_eol;
//簽到
//一年乙個使用者會占用多少空間呢?大約365/8=45.625個位元組,好小,有木有被驚呆?
$redis->setbit($cachekey, $offset, 1);
//查詢簽到情況
$bitstatus = $redis->getbit($cachekey, $offset);
echo 1 == $bitstatus ? '今天已經簽到啦' : '還沒有簽到呢';
echo php_eol;
//計算總簽到次數
echo $redis->bitcount($cachekey) . php_eol;
/*** 計算某段時間內的簽到次數
* 很不幸啊,bitcount雖然提供了start和end引數,但是這個說的是字串的位置,而不是對應"位"的位置
* 幸運的是我們可以通過get命令將value取出來,自己解析。並且這個value不會太大,上面計算過一年乙個使用者只需要45個位元組
* 給我們的**定乙個小目標,執行30年,那麼一共需要1.31kb(就問你屌不屌?)
*///這是個錯誤的計算方式
echo $redis->bitcount($cachekey, 0, 20) . php_eol;
為什麼我設定了bitcount的start後會取不到值?redis> bitcount bits
(integer) 0
redis> setbit bits 1 1
(integer) 0
redis> setbit bits 2 1
(integer) 0
redis> bitcount bits
(integer) 2
redis> bitcount bits 2 -1
(integer) 0
「redis的setbit修改的是bit位置,而bitcount檢查的是byte位置,兩者相差有8的倍數」,再看文件確實是有這個說明,不過太不明顯了
所以在setbit 前把offset * 8 才可以。
參考:$redis = new redis();
$redis->connect('127.0.0.1', 6379, 10);
// 乘以8的原因是這個操作修改的是bit位置
$start = 1;
$offset = $start * 8;
$redis->setbit('bit', $offset, 1);
$count = $redis->bitcount('bit', $start, -1);
var_dump($count);
Redis基於Bitmap實現使用者簽到功能
目錄 很多應用上都有使用者簽到的功能,尤其是配合積分系統一起使用。現在有以下需求 對於使用者簽到資料,如果直接採用資料庫儲存,當出現高併發訪問時,對資料庫壓力會很大,例如雙十一簽到活動。這時候應該採用快取,以減輕資料庫的壓力,redis是高效能的記憶體資料庫,適用於這樣的場景。如果採用string型...
利用 dev mem實現使用者空間驅動
dev mem是物理記憶體的全映像,可以用來訪問物理記憶體,一般用法是open dev mem o rdwr o sync 然後mmap,接著就可以用mmap的位址來訪問物理記憶體,這實際上就是實現使用者空間驅動的一種方法。它的好處參見博文 include include include inclu...
用redis實現使用者登入計數
最近有個問題 實現顯示使用者本月登入日期 累計天數到一定數目可參加活動,和下圖展示的功能類似。過去看過使用redis bitmap進行活躍使用者統計的例子,覺得和本功能非常match,決定用redis的bitset來實現。每個使用者每月產生乙個key,字段意義如下 0 位表示某月1日登入 1表示某月...