Redis分布式锁针对并发量高的服务或接口,能有效预防瞬时有大量访问数据看导致服务雪崩情况发生。通常情况下,有大量被查询数据库的接口数据,通常数据会被保存到缓存,以减少数据库访问压力,更有甚者导致数据库宕机。如某个热点功能的数据加了缓存,并设定缓存过期后刷新。当有大量缓存或者请求量较大的缓存过期,会导致大量请求直接查询数据库,进而出现数据库雪崩情况的发生。通过使用锁机制可以有效避免雪崩问题的发生。
早期分布式锁的解决办法:
$lock = $redis->setnx($key,1);
if ($lock)
{
$redis->expire($key,10);
//业务逻辑...
$redis->del($key);
}
该方式如果遇到请求更新缓存的时间比锁的有效期还长,将导致在缓存更新过程中锁已经失效了,这时,其它请求就会获取到锁,如果前一个请求在缓存更新完毕的时候,直接删除锁会出现误删其它请求创建的锁的情况。
基于redis的分布式锁中setnx+expire非原子操作问题的有效解决方案:
步骤:
1.锁的获取:
Redis::Command('SET',['key',1,['NX','EX'=>10]]);
说明:
key:锁的键名
NX:互斥
EX:过期时间
2.程序执行
3.锁的释放
Redis::Command('DEL',['key']);
分布式锁在早期做项目期间走了不少弯路,通过后来的不断迭代以及redis新版本对set更多支持,终于有了较好的解决方案,希望能帮到有缘人,多多交流,共同进步!