部署环境为分布式部署,定时任务期望其中某台服务器执行,故在代码中使用 Redis::setNx 来创建任务锁,期望拿到锁的服务器执行任务。
// 每天凌晨2点执行更新状态信息
new Crontab('0 2 * * *', function () {
// 负载均衡下有多台服务器,所以拿到更新锁的服务器才能执行任务
$lock = Redis::setNx('update_status_' . date('Y-m-d'), 1);
if ($lock) {
// 执行更新任务
}
});
本地测试没有问题,但是在服务器中,多台服务器都会执行更新任务,请问问题出在哪里?
感谢大佬们帮助,问题找到了。上次发版拉配置中心的配置,拉redis的配置失败了,导致走了默认的配置,应用服务器都连到自己所在服务器的redis了。
Redis 的 setNx 操作实现确实是原子性的,可以保证在并发场景下正确的实现资源锁定,但是在分布式场景下,多个服务器同时连接 Redis 数据库,不同服务器之间存在网络延迟等问题,可能导致 Redis 数据库中的锁被多个服务器同时获取。因此,即使使用 Redis 的 setNx 操作也无法保证在分布式环境下的互斥访问。
为解决这类问题,我们可以采用分布式锁的方式,例如基于 ZooKeeper 或 Redis 实现的分布式锁。这样可以保证分布式环境下的互斥访问,并且可以实现高可用性。具体来说,分布式锁需要保证:
还有就是试试 redis集群自带的key的分片,分片到指定的redis服务器,这样可能就不会造成多个服务器拿到锁。
这是我自己想想的,没有经过实践,如解决了就更好了
你这是什么回答?setnx 可以保证原子性,即使存在网络延迟也不影响这一点,简单的防并发用 setnx 完全没有问题。你这看着像 ChatGPT 回答的。
按照上面说的,是不是会出现死锁吧
看下用的redis是否同一个配置,并且db相同,每台服务器系统的日期设置是否正确
https://www.workerman.net/plugin/42
你可以看下我这个插件的源码
我看你的介绍有后台界面。为啥我下载下来了没有呢 就是你展示的效果图那种
界面是自己项目里的ui
大佬 没有看到有sql文件呢
在源码里,运行的时候就创建好了表
你这锁有点简单了,建议用开源的,不要自己实现。
虽然没看到你解锁的代码。但可以猜测是用
Redis::del()
吧。解锁还是会有问题的。
推荐你用我这个:https://github.com/ichynul/php-redis-lock
如果是分布式的场景下,使用redis ,是不是只有指定到固定的节点去拿锁和加锁呀,要不然就是伪概念红锁来处理
搞那么多乱七八糟的, 分布式场景下推荐用这个锁
推荐用这个https://www.workerman.net/plugin/55
基于symfony/lock的,质量有保证。