Redis构建分布式锁(加锁、解锁)通用函数
use Util\RedisUtil;
class Index {
function redis()
{
$keyname = 'usr';
$redisObj = new RedisUtil('127.0.0.1', 6379);
$start = $this->getMillisecond();
//这里只是模拟瞬间高压力,高并发为多个客户端同时发送请求此redis函数
for ($i = 0; $i < 1000; $i++) {
//须加锁确保计数正确,否则高并发下统计会出错(A用户在get的时候,B用户还未及时set)
$uid = $redisObj->setRedisLock('lockname');
if ($uid) {
/*
$count = $redisObj->get('countname');
$count = $count +1;
$redisObj->set('countname',$count);
*/
/*
* 高并发下,可以把用户的请求$_POST['uid'],先存在redis里,再用crontab依次取出
* do{}while(),一条一条插入数据库;
* */
$data = array(
'id' => $i,
'uid' => $uid,
);
$redisObj->lpush($keyname, json_encode($data));
$redisObj->releaseLock('lockname', $uid);
}
}
$end = $this->getMillisecond();
echo "加入执行时间为:" . ($end - $start) . "ms<br>";
/*
* 可封装为 crontab shell函数,依次取得数据;
* 重连redis ,取出数据,关闭连接;
* */
echo "取出数据";
$ele = null;
do {
$ele = $redisObj->rpop($keyname);
if ($ele) {
echo "get element:" . $ele . "<br>";
// 插入数据库
//$res = $db->insert('tablename',$ele);
// 如果插入数据库失败,则rollover
//if (!$res){$redisObj->rPush($keyname,$ele);}
}
} while ($ele != null);
$popTime = $this->getMillisecond();
echo "结束取出时间为:" . ($popTime - $start) . "ms<br>";
//关闭redis连接;
$redisObj->close();
//清空数据
$redisObj->flushDb();
}
function getMillisecond()
{
list($s1, $s2) = explode(' ', microtime());
return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
}
}
RedisUtil工具类
class RedisUtil
{
private $redis = ""; //redis对象
/**
* @desc 构造函数
*
* @param $host string | redis主机
* @param $port int | 端口
*/
public function __construct($host, $port = 6379)
{
$this->redis = new \Redis();
$this->redis->connect($host, $port);
}
/**
* @desc 加锁方法
*
* @param $lockName string | 锁的名字
* @param $timeout int | 锁的过期时间
*
* @return 成功返回identifier/失败返回false
*/
public function setRedisLock($lockname, $timeout = 2)
{
$uid = uniqid(); //唯一ID;
$timeout = ceil($timeout); //整数;
$end = time() + $timeout;
while (time() < $end) {
//#上锁
if ($this->redis->setnx($lockname, $uid)) {
// #为$lockName设置过期时间,防止死锁
$this->redis->expire($lockname, $timeout);
//上锁成功,锁2S过期,返回 $id;
return $uid;
} else if ($this->redis->ttl($lockname) === -1) {
// #为$lockName设置过期时间,防止死锁
// #检测是否有设置过期时间,没有则加上
// 假设,客户端A上一步没能设置时间就进程奔溃了,
// 客户端B就可检测出来,并设置时间
$this->redis->expire($lockname, $timeout);
}
//Delay execution in microseconds
usleep(0.001);//停止0.001ms
}
//上锁不成功;
return false;
}
/**
* @desc 释放锁
*
* @param $lockName string | 锁名
* @param $identifier string | 锁的唯一值
*
* @param bool
*/
function releaseLock($lockname, $id)
{
//#判断是锁有没有被其他客户端修改
if ($this->redis->get($lockname) === $id) {
$this->redis->multi();
//删除锁;
$this->redis->del($lockname);
$this->redis->exec();
return true;
} else {
//#其他客户端修改了锁,不能删除别人的锁
return false;
}
}
/*
* @set
* */
function set($keyname, $val)
{
$this->redis->set($keyname, $val);
}
/*
* @get
* */
function get($keyname)
{
return $this->redis->get($keyname);
}
/*
* @关闭
* */
function close()
{
$this->redis->close();
}
/*
* @lpush
* */
function lpush($keyname,$val){
$this->redis->lPush($keyname,$val);
}
/*
* @rpush
* */
function rpush($keyname,$val){
$this->redis->rPush($keyname,$val);
}
/*
* @rpop
* */
function rpop($keyname){
return $this->redis->rPop($keyname);
}
/*
* @清空
* */
function flushDb()
{
$this->redis->flushDB();
}
}
参考:https://www.cnblogs.com/phpstudy2015-6/p/6575775.html#_label6

博客介绍了使用Redis构建分布式锁(包含加锁、解锁)的通用函数,还提及了RedisUtil工具类,并给出了参考链接https://www.cnblogs.com/phpstudy2015-6/p/6575775.html#_label6 。
1292

被折叠的 条评论
为什么被折叠?



