利用redis實現使用者簽到
阿新 • • 發佈:2018-12-04
很多網站都提供了簽到功能(這裡不考慮資料落地事宜),並且需要展示最近一個月的簽到情況,如果使用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 "今天是第{$offset}天" . 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的坑
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
為什麼我設定了bitcount的start後會取不到值?
“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);
參考:https://blog.csdn.net/fly910905/article/details/82629687