部署環(huán)境為分布式部署,定時任務(wù)期望其中某臺服務(wù)器執(zhí)行,故在代碼中使用 Redis::setNx 來創(chuàng)建任務(wù)鎖,期望拿到鎖的服務(wù)器執(zhí)行任務(wù)。
// 每天凌晨2點執(zhí)行更新狀態(tài)信息
new Crontab('0 2 * * *', function () {
// 負載均衡下有多臺服務(wù)器,所以拿到更新鎖的服務(wù)器才能執(zhí)行任務(wù)
$lock = Redis::setNx('update_status_' . date('Y-m-d'), 1);
if ($lock) {
// 執(zhí)行更新任務(wù)
}
});
本地測試沒有問題,但是在服務(wù)器中,多臺服務(wù)器都會執(zhí)行更新任務(wù),請問問題出在哪里?
感謝大佬們幫助,問題找到了。上次發(fā)版拉配置中心的配置,拉redis的配置失敗了,導致走了默認的配置,應(yīng)用服務(wù)器都連到自己所在服務(wù)器的redis了。
Redis 的 setNx 操作實現(xiàn)確實是原子性的,可以保證在并發(fā)場景下正確的實現(xiàn)資源鎖定,但是在分布式場景下,多個服務(wù)器同時連接 Redis 數(shù)據(jù)庫,不同服務(wù)器之間存在網(wǎng)絡(luò)延遲等問題,可能導致 Redis 數(shù)據(jù)庫中的鎖被多個服務(wù)器同時獲取。因此,即使使用 Redis 的 setNx 操作也無法保證在分布式環(huán)境下的互斥訪問。
為解決這類問題,我們可以采用分布式鎖的方式,例如基于 ZooKeeper 或 Redis 實現(xiàn)的分布式鎖。這樣可以保證分布式環(huán)境下的互斥訪問,并且可以實現(xiàn)高可用性。具體來說,分布式鎖需要保證:
還有就是試試 redis集群自帶的key的分片,分片到指定的redis服務(wù)器,這樣可能就不會造成多個服務(wù)器拿到鎖。
這是我自己想想的,沒有經(jīng)過實踐,如解決了就更好了
你這鎖有點簡單了,建議用開源的,不要自己實現(xiàn)。
雖然沒看到你解鎖的代碼。但可以猜測是用Redis::del()
吧。
解鎖還是會有問題的。
推薦你用我這個:https://github.com/ichynul/php-redis-lock