使用 Redis bitmap 在微擎内做公众号的签到活动

先说下业务规则 首次签到可获得奖励 以及连续 2 天签到可获得奖励
因为使用的是 openid 而非用户的 uid
因此 此处的设计的 key 为 openid 而判断用户是否签到 的偏移量 为以某个起始时间 未开始的便宜来那个计算
另外还有一种方案是 以当天的日期为 key 而偏移量 则为用户的 uid (此处不采用的原因为 我们的业务 uid 总量不算大 但是 间隔比较大 可能造成很大的 0 间隔)

redis 事件记录 RedisManager
获取 单例 getRedisConn
签到 setSignUser ($openid)
判断今天签到 getTodaySign ($openid)
判断某天签到 getThisDaySign ($openid,$date)
计算总的签到数 countAllSignDay ($openid)
计算连续签到数 countContinueSignDay ($openid)
计算还差几次签到可抽奖 getAwardNeedDays ($openid)
鉴定今天是否能抽奖 decide_award ($openid)

class RedisManager
{
    private static $redisInstance;

    const SIGNSTARTDATA="2019-01-03";
    const CANAWARD=2002;
    const NOTAWARD=2004;
    const SIGNDAYSCANAWARD=2006;
    const SIGNDAYSCANNOTAWARD=2007;
    const FISRTSIGN=2008;
    const REPEATSIGN=2009;
    const SUFFIX="_2019";
    const PREFIX="sign_";

    private function __construct(){}

     static public function getRedisConn(){
        if(!self::$redisInstance instanceof self){
            self::$redisInstance = new self;
        }
        $temp = self::$redisInstance;
        return $temp->connRedis();
    }

    static  function connRedis()
    {     
        try {
            $redis_ocean = new Redis();
            $redis_ocean->connect("127.0.0.1","6333");
            $redis_ocean->auth("Zdklingchen");

        }catch (Exception $e){
            echo $e->getMessage().'
'; } return $redis_ocean; } static function setSignUser($openid){//签到 $redis=RedisManager::getRedisConn(); $cacheKey=RedisManager::PREFIX.$openid.RedisManager::SUFFIX; $startDate = RedisManager::SIGNSTARTDATA; $todayDate = date("Y-m-d"); $startTime = strtotime($startDate); $todayTime = strtotime($todayDate); $offset = floor(($todayTime - $startTime) / 86400); return $redis->setBit($cacheKey, $offset, 1); } static function getTodaySign($openid){//判断某个openid 今天 $redis=RedisManager::getRedisConn(); $cacheKey=RedisManager::PREFIX.$openid.RedisManager::SUFFIX; $startDate = RedisManager::SIGNSTARTDATA; $todayDate = date("Y-m-d"); $startTime = strtotime($startDate); $todayTime = strtotime($todayDate); $offset = floor(($todayTime - $startTime) / 86400); $bitStatus = $redis->getBit($cacheKey, $offset); return $bitStatus; } static function getThisDaySign($openid,$date){//判断某个openid 是否在某天签到 0/1 $redis=RedisManager::getRedisConn(); $cacheKey=RedisManager::PREFIX.$openid.RedisManager::SUFFIX; $startDate = RedisManager::SIGNSTARTDATA; $todayDate = $date; $startTime = strtotime($startDate); $todayTime = strtotime($todayDate); $offset = floor(($todayTime - $startTime) / 86400); $bitStatus = $redis->getBit($cacheKey, $offset); return $bitStatus; } static function countAllSignDay($openid){//计算累计签到次数 $redis=RedisManager::getRedisConn(); $cacheKey=RedisManager::PREFIX.$openid.RedisManager::SUFFIX; return $redis->bitCount($cacheKey); } static function countContinueSignDay($openid){//计算连续签到次数 $redis=RedisManager::getRedisConn(); $cacheKey=RedisManager::PREFIX.$openid.RedisManager::SUFFIX; $todayIsSign=RedisManager::getTodaySign($openid); if ($todayIsSign == 0) { $todayDate=date("Y-m-d",strtotime("-1 day")); }else{ $todayDate = date("Y-m-d"); } $startDate = RedisManager::SIGNSTARTDATA; $startTime = strtotime($startDate); $todayTime = strtotime($todayDate); $offset = floor(($todayTime - $startTime) / 86400); $countContinueSignDayNum=0; for ($i=$offset; $i >= 0; $i--) { $BitRes=$redis->getBit($cacheKey, $i); if ($BitRes == 1) { $countContinueSignDayNum++; continue; }else{ break; } } return $countContinueSignDayNum; } static function getAwardNeedDays($openid){ $todayIsSign=RedisManager::getTodaySign($openid); $totalCountSign=RedisManager::countAllSignDay($openid); if ($totalCountSign == 1 && $todayIsSign == 1) {//今天还没签到 $data=array( "code"=>RedisManager::FISRTSIGN, "needsDays"=>2, "msg"=> "First sign has sign,can get arawd", ); return $data; } if ($totalCountSign == 0 && $todayIsSign == 0) {//今天还没签到 $data=array( "code"=>RedisManager::FISRTSIGN, "needsDays"=>0, "msg"=> "First sign has not sign", ); return $data; }else{ $YesterDay=date("Y-m-d",strtotime("-1 day")); $YesterDaySignData=RedisManager::getThisDaySign($openid,$YesterDay); if ($YesterDaySignData == 0) {//昨日没签到 if ($todayIsSign == 0) { $data=array( "code"=>RedisManager::SIGNDAYSCANAWARD, "needsDays"=>2, "msg"=> "Today is not sign And YesterDay is not sign ", ); return $data; }else{ $data=array( "code"=>RedisManager::SIGNDAYSCANAWARD, "needsDays"=>1, "msg"=> "Today has sign But YesterDay is not sign ", ); return $data; } }else{ $continueSignNum=RedisManager::countContinueSignDay($openid); if ($totalCountSign == $continueSignNum && $totalCountSign > 0 ) {//签到一直没间断 if ($todayIsSign == 0) { if ($totalCountSign%2 == 0 ) { $data=array( "code"=>RedisManager::SIGNDAYSCANAWARD, "needsDays"=>1, "msg"=> "Today is not sign But sign is continue ", ); return $data; }else{ $data=array( "code"=>RedisManager::SIGNDAYSCANAWARD, "needsDays"=>2, "msg"=> "Today is not sign But sign is continue ", ); return $data; } }else{//今天签到了 if ($totalCountSign%2 == 0 ) { $data=array( "code"=>RedisManager::SIGNDAYSCANAWARD, "needsDays"=>1, "msg"=> "Today has sign And sign is continue ", ); return $data; }else{ $data=array( "code"=>RedisManager::SIGNDAYSCANAWARD, "needsDays"=>2, "msg"=> "Today has sign And sign is continue ", ); return $data; } } }else{ if ($todayIsSign == 0) { if ($continueSignNum%2 == 0 ) { $data=array( "code"=>RedisManager::SIGNDAYSCANAWARD, "needsDays"=>1, "msg"=> "Today is not sign But sign is not continue ", ); return $data; }else{ $data=array( "code"=>RedisManager::SIGNDAYSCANAWARD, "needsDays"=>2, "msg"=> "Today is not sign But sign is not continue ", ); return $data; } }else{ if ($continueSignNum%2 == 0 ) { $data=array( "code"=>RedisManager::SIGNDAYSCANAWARD, "needsDays"=>2, "msg"=> "Today is has sign But sign is not continue ", ); return $data; }else{ $data=array( "code"=>RedisManager::SIGNDAYSCANAWARD, "needsDays"=>1, "msg"=> "Today is has sign But sign is not continue ", ); return $data; } } } } } } static function decide_award($openid){ //返回一个数组 2004 不抽奖 2002抽奖 $todayIsSign=RedisManager::getTodaySign($openid); $totalCountSign=RedisManager::countAllSignDay($openid); if ($todayIsSign == 0) {//今天没签到 $data=array( "code"=>RedisManager::NOTAWARD, "msg"=>"今日还没签到", ); return $data; } if ($todayIsSign == 1 && $totalCountSign == 1) {//首次签到 今天签到 +总签到数=1 $data=array( "code"=>RedisManager::CANAWARD, "msg"=>"首次签到", ); return $data; }else{ $YesterDay=date("Y-m-d",strtotime("-1 day")); $YesterDaySignData=RedisManager::getThisDaySign($openid,$YesterDay); if ($YesterDaySignData == 0) { //昨天没签到 $data=array( "code"=>RedisManager::NOTAWARD, "msg"=>"签到成功,但是您昨天没签到,明天继续签到可获得奖励", ); return $data; }else{//因为今天已经签到 所以 连续签到从今天算 最小为1 $continueSignNum=RedisManager::countContinueSignDay($openid); if ($totalCountSign == 2 && $continueSignNum == 2 ) {//总签到 跟连续签到 都为2 则说明昨天是首次签到 $data=array( "code"=>RedisManager::NOTAWARD, "msg"=>"签到成功,明天继续签到可获得奖励", ); return $data; }else{//昨天签到不是首次签到 if ($totalCountSign == $continueSignNum && $totalCountSign > 0 ) {//首次签到一直没断 if ($totalCountSign%2 == 0 ) { //偶数次不发 $data=array( "code"=>RedisManager::NOTAWARD, "msg"=>"签到成功,明天继续签到可获得奖励", ); return $data; }else{ $data=array( "code"=>RedisManager::CANAWARD, "msg"=>"签到成功,今天可抽奖", ); return $data; } }else{ if ($continueSignNum%2 == 0 ) { //偶数次发 $data=array( "code"=>RedisManager::CANAWARD, "msg"=>"签到成功,今天可抽奖", ); return $data; }else{ $data=array( "code"=>RedisManager::NOTAWARD, "msg"=>"签到成功,明天继续签到可获得奖励", ); return $data; } } } } } } private function __clone(){} }

 

你可能感兴趣的:(redis,php)