php双写绕过,高并发下缓存与数据库双写不一致解决方案
解決方案
在高并發場景下,數據庫和緩存雙寫不一致情況,我們可以當寫入數據庫后刪除緩存,當查的時候先查緩存,如果緩存為空再查數據庫,最后寫入緩存,但是這樣還是存在一個問題。
如圖所示,當出現這種情況時該方案就會出現問題,線程2阻塞一段時間后,又把stock=9有更新到緩存中,而數據庫中的stock=10,下一次查時,會查到緩存中的stock=9
方案優化
對于這種問題,如果業務場景對數據一致性沒有那么高,我們可以在更新緩存時設置一個過期時間,過期之后緩存也就不存在了,還有一種我們可以使用延遲雙刪方案。
間隔的n秒沒有統一的標準,完全看個人的經驗,所以這種方案還是存在問題。最佳解決方案時使用分布式鎖。
我們可以使用redis讀鎖和寫鎖。我們使用redisson實現分布式鎖。
Redisson
注入RedissonClient對象@Bean
public RedissonClient redissonClient(){
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
return Redisson.create(config);
}
讀鎖請求@GetMapping("read")
public String read(){
RReadWriteLock readWriteLock = redissonClient.getReadWriteLock(RedisConstant.READ_WRITE_LOCK);
//讀之前加讀鎖,讀鎖的作用就是等待該lockkey釋放寫鎖以后再讀
RLock rLock = readWriteLock.readLock();
try {
rLock.lock();
String uuid = redisTemplate.opsForValue().get("uuid");
return uuid;
}finally {
rLock.unlock();
}
}
寫鎖請求@GetMapping("write")
public String write() throws InterruptedException {
RReadWriteLock readWriteLock = redissonClient.getReadWriteLock(RedisConstant.READ_WRITE_LOCK);
//寫之前加寫鎖,寫鎖加鎖成功,讀鎖只能等待
RLock rLock = readWriteLock.writeLock();
String s = "";
try {
rLock.lock();
s = UUID.randomUUID().toString();
Thread.sleep(10000);
redisTemplate.opsForValue().set("uuid",s);
}finally {
rLock.unlock();
}
return s;
}
總結
以上是生活随笔為你收集整理的php双写绕过,高并发下缓存与数据库双写不一致解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php中post,php中post的用法
- 下一篇: 网页连接不上java服务端,用Java插