PHP语言使用Redis NoSQL服务器二进制数据类型实现大数据情况下签到功能
目录
问题
实现用户每日签到功能不难,但随着用户量上升之后,不论是存储还是判断对数据量来说都很麻烦;假如每天有100万用户签到,如何存储、判断签到和显示每月签到记录。
解决方式
通过Redis 二进制数据实现签到。
封装签到类
在其中将redis的链接、储存、查询等操作进行封装,提供签到、补签、查看当月签到记录等功能接口。
具体代码如下:
<?php
class Sign
{
private $link;
private static $signList = 'signDay';
public function __construct()
{
$this->link = $this->connect();
}
private function connect()
{
$redis = new \Redis();
$host = '127.0.0.1'; // Redis服务器地址
$port = 6379; // Redis端口号,默认是6379
$timeout = 0; // 连接超时时间(可选,默认为0,代表无超时,单位秒)
$redis->connect($host, $port, $timeout);
return $redis;
}
/**
* 进行签到
* @return bool
*/
public function addDay()
{
// 判断今日是否签到
$nowD = date('d');
$isSign = $this->isSign($nowD-1);
if (!in_array($isSign, ['0', '1'], true)) {
// 进行签到
return $this->link->append(self::$signList, '1');
}
return true;
}
/**
* 获取签到列表
* @return string
*/
public function getDayList()
{
return $this->link->getRange(self::$signList, 0, -1);
}
/**
* 对指定日期进行补签
* @param string $d
* @return bool|int
*/
public function repairDay(string $d)
{
$nowDay = date('d');
if ($nowDay == $d) {
return $this->addDay();
}
// 判断补签日期是否已签到
$offset = $d - 1;
if ($this->isSign($offset)) {
return true;
}
return $this->link->setRange(self::$signList, $offset, 1);
}
/**
* 是否签到
* @param $offset:偏移量
* @return string
*/
private function isSign($offset)
{
return $this->link->getRange(self::$signList, $offset, $offset);
}
public function __destruct()
{
$this->link->close();
}
}
功能调用
在实例化后,调用当日签到,补签本月6号的记录,之后查询本月签到记录。
示例如下:
<?php
require_once './Sign.php';
$obj = new Sign();
// 签到
$info = $obj->addDay();
// 补签 本月6号的记录
$info = $obj->repairDay('6');
// 获取签到列表
$dayList = $obj->getDayList();
print_r(str_split($dayList, 1));
运行结果:
总结
PHP语言使用Redis NoSQL服务器二进制数据类型实现大数据情况下签到功能。