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; } }