在线人数统计业务是我们开发web肯定要设计的业务逻辑,本文就会给出几种设计方案,来分析下各个方案的优缺点:
$start_time = mktime(0, 0, 0, 9, 5); //monday
for ($i=0; $i < 6; $i++) {
$day_start_time = $start_time + 86400 * $i; //every day begin time
$day_end_time = $day_start_time + 86400; //every day end time
$online_user_num = mt_rand(100000, 300000); //online user between 100000 and 300000
for ($j=1; $j < $online_user_num; $j++) {
$user_id = mt_rand(1, 1000000);
$redis->zadd('000|online_users_day_'.$i, mt_rand($day_start_time, $day_end_time), $user_id);
}
}
//note: 统计每天的在线总人数
for ($i=0; $i < 6; $i++) {
print_r($redis->zsize('000|online_users_day_'.$i). "\n");
}
//note: 统计最近6天都在线的人数
var_dump($redis->zInter('000|online_users_day_both_6',
[
'000|online_users_day_0',
'000|online_users_day_1',
'000|online_users_day_2',
'000|online_users_day_3',
'000|online_users_day_4',
'000|online_users_day_5'
]
));
//note: 统计出近6天中共有多少上线
$redis->zunion('000|online_users_day_total_6', ['000|online_users_day_0', '000|online_users_day_1', '000|online_users_day_2', '000|online_users_day_3', '000|online_users_day_4', '000|online_users_day_5']);
//note: 统计某个时间段总共在线用户
print_r($redis->zcount('000|online_users_day_5', mktime(13, 0, 0, 9, 10), mktime(14, 0, 0, 9, 10)));
//note: 统计某个时间段在线用户名单
print_r($redis->zrangebyscore('000|online_users_day_5', mktime(13, 0, 0, 9, 10), mktime(14, 0, 0, 9, 10),
array('withscores' => TRUE)));
//note set 一般聚合
for ($i=0; $i < 6; $i++) {
$online_user_num = mt_rand(100000, 300000); //online user between 100000 and 300000
for ($j=1; $j < $online_user_num; $j++) {
$user_id = mt_rand(1, 1000000);
$redis->sadd('001|online_users_day_'.$i, $user_id);
}
}
//note 判断某个用户是否在线
var_dump($redis->sIsMember('001|online_users_day_5', 100030));
//note 每天在线用户总量的统计
for ($i=0; $i < 6; $i++) {
print_r($redis->ssize('001|online_users_day_'.$i). "\n");
}
//note 对不同时间段的在线用户名单进行聚合
print_r($redis->sInterStore('001|online_users_day_both_4and5', '001|online_users_day_4', '001|online_users_day_5'). "\n");
//note 对指定的时间段的在线用户名单进行统计
print_r($redis->sUnionStore('001|online_users_day_total_4add5', '001|online_users_day_4', '001|online_users_day_5'). "\n");
//note 哪天上线哪天没上线
print_r($redis->sDiffStore('001|online_users_day_diff_4jian5', '001|online_users_day_4', '001|online_users_day_5'). "\n");
// note HyperLogLog 只需要知道在线总人数
for ($i=0; $i < 6; $i++) {
$online_user_num = mt_rand(100000, 300000); //online user between 100000 and 300000
var_dump($online_user_num);
for ($j=1; $j < $online_user_num; $j++) {
$user_id = mt_rand(1, 1000000);
$redis->pfadd('002|online_users_day_'.$i, [$user_id]);
}
}
$count = 0;
for ($i=0; $i < 3; $i++) {
$count += $redis->pfcount('002|online_users_day_'.$i);
print_r($redis->pfcount('002|online_users_day_'.$i). "\n");
}
var_dump($count);
//note 3 days total online num
var_dump($redis->pfmerge('002|online_users_day_both_3', ['002|online_users_day_0', '002|online_users_day_1', '002|online_users_day_2']));
var_dump($redis->pfcount('002|online_users_day_both_3'));
//note bitmap 综合前面3个的优缺点
for ($i=0; $i < 6; $i++) {
$online_user_num = mt_rand(100000, 300000); //online user between 100000 and 300000
for ($j=1; $j < $online_user_num; $j++) {
$user_id = mt_rand(1, 1000000);
$redis->setbit('003|online_users_day_'.$i, $user_id, 1);
}
}
//note userid today whether online
var_dump($userid = mt_rand(1, 1000000));
var_dump($redis->getbit('003|online_users_day_5', $userid));
//note how many user is online
var_dump($redis->bitcount('003|online_users_day_5'));
//note 6 days both online
var_dump($redis->bitop('AND', '003|online_users_day_both_6', '003|online_users_day_0', '003|online_users_day_1', '003|online_users_day_2', '003|online_users_day_3', '003|online_users_day_4', '003|online_users_day_5'));
var_dump($redis->bitcount('003|online_users_day_both_6'));
//note 6 days total online
var_dump($redis->bitop('OR', '003|online_users_day_total_6', '003|online_users_day_0', '003|online_users_day_1', '003|online_users_day_2', '003|online_users_day_3', '003|online_users_day_4', '003|online_users_day_5'));
var_dump($redis->bitcount('003|online_users_day_total_6'));
//note 6 days only one online
var_dump($redis->bitop('XOR', '003|online_users_day_only_one_6', '003|online_users_day_0', '003|online_users_day_1', '003|online_users_day_2', '003|online_users_day_3', '003|online_users_day_4', '003|online_users_day_5'));
var_dump($redis->bitcount('003|online_users_day_only_one_6'));