用redis实现用户登录计数
2014-09-03 11:28
323 查看
最近有个问题 :实现显示用户本月登录日期 ,累计天数到一定数目可参加活动,和下图展示的功能类似。
过去看过使用redis bitmap进行活跃用户统计的例子,觉得和本功能非常match,决定用redis的bitset来实现。
每个用户每月产生一个key,字段意义如下 0 位表示某月1日登录 ,1表示某月2日登录,以此类推。
每个用户一月的活跃度需要8byte,1W用户每年需要1W*12*8byte 约1M数据
用户每次登录系统,需要用setBit设置用户本日登录,可用bitcount的到用户本月登录天数总和,因为PHP原生不对bitset进行支持,采用get得到字符串进行操作得到用户登录日期
测试代码如下:
大小: 12.7 KB
大小: 349.3 KB
查看图片附件
过去看过使用redis bitmap进行活跃用户统计的例子,觉得和本功能非常match,决定用redis的bitset来实现。
每个用户每月产生一个key,字段意义如下 0 位表示某月1日登录 ,1表示某月2日登录,以此类推。
每个用户一月的活跃度需要8byte,1W用户每年需要1W*12*8byte 约1M数据
用户每次登录系统,需要用setBit设置用户本日登录,可用bitcount的到用户本月登录天数总和,因为PHP原生不对bitset进行支持,采用get得到字符串进行操作得到用户登录日期
测试代码如下:
<?php /** * * User: shikiliu * Date: 14-8-27 */ class ActiveDate { private $redisConf = array('host' => 'localhost', 'port' => 6379); private $redis = null; private $userPrefix = 'user_active_'; /** * 设置用户某天登录过 */ public function setActiveDate($userId, $time = null) { if (empty($time)) { $time = time(); } $redis = $this->getRedis(); $redis->setBit($this->userPrefix . $userId . '_' . date('Y-m', $time), intval(date('d', $time)) - 1, 1); return true; } /** * 得到用户本月登录天数 * redis >= 2.6.0 才可以 */ public function getActiveDatesCount($userId, $time = null){ if (empty($time)) { $time = time(); } $redis = $this->getRedis(); return $redis->bitcount($this->userPrefix . $userId . '_' . date('Y-m', $time)); } /** * 得到用户某月所有的登录过日期 */ public function getActiveDates($userId, $time = null) { $result = array(); if (empty($time)) { $time = time(); } $redis = $this->getRedis(); $strData = $redis->get($this->userPrefix . $userId . '_' . date('Y-m', $time)); if (empty($strData)) { return $result; } $monthFirstDay = mktime(0, 0, 0, date("m", $time), 1, date("Y", $time)); $maxDay = cal_days_in_month(CAL_GREGORIAN, date("m", $time), date("Y", $time)); $charData = unpack("C*", $strData); for ($index = 1; $index <= count($charData); $index++) { for ($bit = 0; $bit < 8; $bit++) { if ($charData[$index] & 1 << $bit) { //$intervalDay = ($index - 1) * 8 + 8-$bit; $intervalDay = $index * 8 -$bit; //如果数据有大于当月最大天数的时候 if ($intervalDay > $maxDay) { return $result; } $result [] = date('Y-m-d', $monthFirstDay + ($intervalDay-1) * 86400); } } } return $result; } /** * redis连接 */ private function getRedis() { if (empty($this->redis)) { $redis = new Redis(); if (!$redis->connect($this->redisConf['host'], $this->redisConf['port'])) { throw new Exception("Error Redis Connect", 100); } $redis->select(3); $this->redis = $redis; } return $this->redis; } } $activeDate = new ActiveDate(); var_dump($activeDate->setActiveDate(514540767,1406822600));// 2014/8/1 0:3:20 var_dump($activeDate->setActiveDate(514540767,1407225600));// 2014/8/5 16:0:0 var_dump($activeDate->setActiveDate(514540767,1409472000));// 2014/8/31 16:0:0 var_dump($activeDate->getActiveDates(514540767)); var_dump($activeDate->getActiveDatesCount(514540767));
大小: 12.7 KB
大小: 349.3 KB
查看图片附件
相关文章推荐
- redis实现网站最新登录用户功能
- 面试题:用Redis和任意语言实现一段恶意登录保护的代码,限制1小时内每用户Id最多只能登录5次
- 利用Redis实现亿级别用户登录统计(活跃度以及登录次数统计)
- 面试题之redis实现限制1小时内每用户Id最多只能登录5次
- jedis 实现 redis 统计一个用户在一段时间内的登录次数
- 面试题:用Redis和任意语言实现一段恶意登录保护的代码,限制1小时内每用户Id最多只能登录5次
- 利用Redis实现亿级别用户登录统计(活跃度以及登录次数统计)
- 图文演示Flash+ASP实现用户登录/注册程序第1/2页
- ajax 无刷新实现用户登录
- ajax 无刷新实现用户登录
- [转]C# 调用API,实现注销远程登录本机的用户
- 使用AjaxPro框架实现无刷新用户登录验证【原创】
- 在ASP.NET AJAX中使用应用程序服务和本地化(2):示例程序:实现用户登录和注销
- 在jsp中用bean和servlet联合实现用户注册、登录
- C# 调用API,实现注销远程登录本机的用户
- 在Forms验证模式下,实现多个站点(SubDomain相同)共享同一用户登录状态
- 在jsp中用bean和servlet联合实现用户注册、登录
- 在jsp中用bean和servlet联合实现用户注册、登录
- ATM系统实现[1]——用户登录界面[00原创]
- 在jsp中用bean和servlet联合实现用户注册、登录