当前位置: 首页 > 后端技术 > PHP

PHP实现Redis并发锁实例

时间:2023-03-29 15:40:05 PHP

前言在一些业务场景中,当用户或进程同时处理一段逻辑时,会造成异常冲突。所以并发锁的使用只让获得锁的进入下一步处理,没有获得锁的进入等待或者直接拒绝操作。这可能非常有效。很大程度上避免并发冲突。示例Redis执行命令在单线程中按顺序执行。使用Redis命令实现锁功能,就是先执行先拿到锁。环境说明:下面的例子中使用了composer安装的predis/predis:^1.1扩展连接Redisconfig()函数用于获取Redis服务配置,可以替换成你环境中对应的值'tcp','host'=>config('redis.host'),'port'=>config('redis.port'),];//当没有配置密码时,Parameter中不传入密码项if(config('redis.password'))$config['password']=config('redis.password');//所有键名都带有默认前缀self::$client=newClient($config,['prefix'=>config('redis.prefix')]);}返回自我::$客户;}/***添加自定义并发锁*原理是redis单线程运行*@paramstring$name锁名*@paramint$ttl锁持续时间,秒*@paramint$retries重试次数*@paramint$interval重试间隔,毫秒*@returnbool本次调用是否成功锁定锁*/publicstaticfunctionlock(string$name,int$ttl=10,int$retries=0,int$interval=200){$redis=自我::客户();$key=self::LOCK_PREFIX。$名称;$is_lock=false;//默认是锁失败$interval=$interval*1000;//毫秒到微秒//默认只尝试一次,如果设置了重试次数,则叠加$num=1+$retries;for($i=1;$i<=$num;$i++){//键操作,当键不存在且过期时间时设置值$is_lock=(bool)$redis->set($key,1,'NX','EX',$ttl);如果($is_lock){中断;}elseif($retries>0&&$i<$num){//间隔一段时间后重试;如果是最后一次重试,不休眠usleep($interval);}}返回$is_lock;}/***释放自定义并发锁*@paramstring$name锁名*@returnbool是否成功*/publicstaticfunctionunlock(string$name){$key=self::LOCK_PREFIX.$名称;返回(bool)self::client()->del([$key]);}}//使用//lock,返回true表示获取锁成功$lk=Redis::lock('lock_key');if($lk){//做一些业务处理}//解锁,解锁后业务处理,解锁后,其他人可以重新获取锁Redis::unlock('lock_key');结束。