利用redis实现用户签到

本文介绍如何利用Redis的Bitmap数据结构实现用户签到功能,包括签到记录的存储与查询,以及统计签到次数的方法。通过示例代码演示了如何计算用户签到的偏移量,并正确使用BITCOUNT命令获取指定时间段内的签到次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

很多网站都提供了签到功能(这里不考虑数据落地事宜),并且需要展示最近一个月的签到情况,如果使用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.youkuaiyun.com/fly910905/article/details/82629687

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值