redis的watch配合事务可以实现乐观锁机制
// 在test1方法中连接redis
$config = config('redis.');
$redis = new \Redis();
$redis->connect($config['redis_host'],$config['redis_port']);
$redis->auth($config['redis_auth']);
//设置key的值为10
$strKey = 'Test_bihu_age';
$re = $redis->set($strKey,10);
$age = $redis->get($strKey);
echo "1---- Current Age:{$age} ---- <br/><br/>"; //10
// 开启事务
$redis->watch($strKey);
$redis->multi();
//在这个时候新开了一个新会话执行
$re1 = $redis->set($strKey,20); //新会话
print_dump($re1);
echo "2---- Current Age:{$age} ---- <br/><br/>"; //10
$re2 = $redis->set($strKey,30);
// 睡眠5秒,若这5秒期间有其他地方修改了这个"Test_bihu_age"的key(不是上面的set20和set30),则multi至exec期间的redis代码均失效回滚(若有mysql代码是不会回滚的)
sleep(5);
echo "3---- Current Age:{$age} ---- <br/><br/>"; //10
print_dump($re2);
$re3 = $redis->exec();
/* array(2) {
[0]=>
bool(true)
[1]=>
bool(true)
} */
print_dump($re3);
if($re3){
print_dump('期间没有修改过key');
// 进行mysql的操作
Db::name("ad")->where('id',95)->setField('sort',1);
}else{
print_dump('期间修改过key需要回滚redis');
// 无需进行mysql的操作
}
$age = $redis->get($strKey);
echo "4---- Current Age:{$age} ---- <br/><br/>"; //30
die;在test2方法中,若在test1的sleep 5秒期间修改了Test_bihu_age的值,则test1方法sleep5秒后echo "4---- Current Age:{$age} ---- <br/><br/>"; 的值不再是30,而是test2方法中修改后的值
redis配合watch实现秒杀&抢购功能
$config = config('redis.');
$redis = new \Redis();
$redis->connect($config['redis_host'],$config['redis_port']);
$redis->auth($config['redis_auth']);
$mywatchkey = $redis->get("mywatchkey");
$rob_total = 6; //抢购数量
if($mywatchkey<$rob_total){
$redis->watch("mywatchkey");
$redis->multi();
//设置延迟,方便测试效果。
sleep(2);
//插入抢购数据
$redis->hSet("mywatchlist","user_id_".mt_rand(1, 9999),time());
$redis->set("mywatchkey",$mywatchkey+1);
$rob_result = $redis->exec();
print_dump($rob_result);
if($rob_result){
$mywatchlist = $redis->hGetAll("mywatchlist");
echo "抢购成功!";
echo "剩余数量:".($rob_total-$mywatchkey-1)."</br>";
echo "用户列表:";
var_dump($mywatchlist);
}else{
echo "手气不好,再抢购!";exit;
}
}