您的位置:首页 > 数据库 > Redis

用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得到字符串进行操作得到用户登录日期
测试代码如下:

 
<?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

查看图片附件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: