用redis实现用户登录计数

5 篇文章 0 订阅

最近有个问题 :实现显示用户本月登录日期 ,累计天数到一定数目可参加活动,和下图展示的功能类似。



 
过去看过使用redis bitmap进行活跃用户统计的例子,觉得和本功能非常match,决定用redis的bitset来实现。
 
每个用户每月产生一个key,字段意义如下 0 位表示某月1日登录  ,1表示某月2日登录,以此类推。
 
每个用户一月的活跃度需要8byte,1W用户每年需要1W*12*8byte 约1M数据


 
 
用户每次登录系统,需要用setBit设置用户本日登录,可用bitcount的到用户本月登录天数总和,因为PHP原生不对bitset进行支持,采用get得到字符串进行操作得到用户登录日期
测试代码如下:
 
  1. <?php  
  2.   
  3. /** 
  4.  * 
  5.  * User: shikiliu 
  6.  * Date: 14-8-27 
  7.  */  
  8.   
  9. class ActiveDate  
  10. {  
  11.   
  12.   
  13.     private $redisConf = array('host' => 'localhost''port' => 6379);  
  14.   
  15.     private $redis = null;  
  16.   
  17.     private $userPrefix = 'user_active_';  
  18.   
  19.   
  20.     /** 
  21.      * 设置用户某天登录过 
  22.      */  
  23.     public function setActiveDate($userId$time = null)  
  24.     {  
  25.   
  26.         if (empty($time)) {  
  27.   
  28.             $time = time();  
  29.         }  
  30.   
  31.         $redis = $this->getRedis();  
  32.   
  33.         $redis->setBit($this->userPrefix . $userId . '_' . date('Y-m'$time), intval(date('d'$time)) - 1, 1);  
  34.   
  35.         return true;  
  36.     }  
  37.   
  38.   
  39.     /** 
  40.      * 得到用户本月登录天数 
  41.      * redis >= 2.6.0 才可以 
  42.      */  
  43.     public function getActiveDatesCount($userId$time = null){  
  44.   
  45.         if (empty($time)) {  
  46.   
  47.             $time = time();  
  48.         }  
  49.   
  50.         $redis = $this->getRedis();  
  51.   
  52.         return $redis->bitcount($this->userPrefix . $userId . '_' . date('Y-m'$time));  
  53.   
  54.     }  
  55.   
  56.   
  57.     /** 
  58.      * 得到用户某月所有的登录过日期 
  59.      */  
  60.     public function getActiveDates($userId$time = null)  
  61.     {  
  62.   
  63.   
  64.         $result = array();  
  65.   
  66.         if (empty($time)) {  
  67.   
  68.             $time = time();  
  69.         }  
  70.   
  71.         $redis = $this->getRedis();  
  72.   
  73.         $strData = $redis->get($this->userPrefix . $userId . '_' . date('Y-m'$time));  
  74.   
  75.         if (empty($strData)) {  
  76.             return $result;  
  77.         }  
  78.   
  79.         $monthFirstDay = mktime(0, 0, 0, date("m"$time), 1, date("Y"$time));  
  80.   
  81.         $maxDay = cal_days_in_month(CAL_GREGORIAN, date("m"$time), date("Y"$time));  
  82.   
  83.         $charData = unpack("C*"$strData);  
  84.   
  85.         for ($index = 1; $index <= count($charData); $index++) {  
  86.   
  87.             for ($bit = 0; $bit < 8; $bit++) {  
  88.   
  89.                 if ($charData[$index] & 1 << $bit) {  
  90.   
  91.                     //$intervalDay = ($index - 1) * 8 + 8-$bit;  
  92.                     $intervalDay = $index  * 8 -$bit;  
  93.                     //如果数据有大于当月最大天数的时候  
  94.                     if ($intervalDay > $maxDay) {  
  95.   
  96.                         return $result;  
  97.   
  98.                     }  
  99.   
  100.                     $result [] = date('Y-m-d'$monthFirstDay + ($intervalDay-1) * 86400);  
  101.   
  102.                 }  
  103.   
  104.             }  
  105.   
  106.         }  
  107.   
  108.         return $result;  
  109.   
  110.   
  111.     }  
  112.   
  113.   
  114.     /** 
  115.      *  redis连接 
  116.      */  
  117.     private function getRedis()  
  118.     {  
  119.   
  120.         if (empty($this->redis)) {  
  121.   
  122.   
  123.             $redis = new Redis();  
  124.   
  125.             if (!$redis->connect($this->redisConf['host'], $this->redisConf['port'])) {  
  126.   
  127.                 throw new Exception("Error Redis Connect", 100);  
  128.   
  129.             }  
  130.   
  131.             $redis->select(3);  
  132.   
  133.             $this->redis = $redis;  
  134.   
  135.   
  136.         }  
  137.   
  138.         return $this->redis;  
  139.   
  140.     }  
  141.   
  142.   
  143. }  
  144.   
  145.   
  146. $activeDate = new ActiveDate();  
  147.   
  148. var_dump($activeDate->setActiveDate(514540767,1406822600));//  2014/8/1 0:3:20  
  149. var_dump($activeDate->setActiveDate(514540767,1407225600));//  2014/8/5 16:0:0  
  150. var_dump($activeDate->setActiveDate(514540767,1409472000));//  2014/8/31 16:0:0  
  151.   
  152. var_dump($activeDate->getActiveDates(514540767));  
  153.   
  154. var_dump($activeDate->getActiveDatesCount(514540767));  
  155.       
 转自 博客
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值