分布式鎖和事務一起使用失效
原因: 在事務中使用redis分布式鎖,方法一旦執行事務生效,接着是redis分布式鎖生效,代碼執行完后釋放redis分布式鎖、然后提交事務數據,最后事務結束。在這個過程中事務沒有提交之前分布式鎖已經被釋放,導致分布式鎖失效
解決:在調用事務方法之前先加分布式鎖
@Transactional
public void update(int id) {
boolean lock = redisLock.lock(id);
if (!lock) {
throw new RuntimeException(“當前人數過多,請稍后再試”);
}
/*
業務代碼在該區域
*/
redisLock.unlock(id);
}
在上面的代碼中,我們同時使用了@transactional和redis分布式鎖(其他鎖同理,比如synchronized同步鎖也會出現這個問題)
問題分析
上面這個例子是無法保證數據的一致性.由於spring的aop,會在update方法之前開啟事務,之后再加鎖,當鎖住的代碼執行完成后,再提交事務,因此鎖住的代碼塊執行是在事務之內執行的,可以推斷在代碼塊執行完時,事務還未提交,鎖已經被釋放,此時其他線程拿到鎖之后進行鎖住的代碼塊,讀取的庫存數據不是最新的。
解決方法
我們可以在update方法之前就加上鎖,在還沒有開事務之前就加鎖,那么就可以保證線程的安全性,從而不會出現臟讀和數據不一致性等情況.
業務超時執行
鎖失效時間設置問題
鎖定了10s后過期,但業務執行了30s(可能碰到fullgc,死循環等場景)。
主從切換問題
業務1從主獲取鎖,此時主掛機了,從晉升為主,恰好此時從未同步這個鎖的值 。
原文鏈接:https://blog.csdn.net/he247052163/article/details/119413877