雪崩时,没有一片雪花是无辜的!
在高并发的场景下,缓存往往成为缓解数据库I/O压力最完美的选择;将并发高峰期请求频繁的数据放入缓存,请求派发时优先操作(读取或者修改)缓存中的数据,然后在异步同步到数据库中。这种处理方式在理想情况下是很完美的,它使得数据库I/O不再试并发瓶颈,指数扩张了整个系统的吞吐量。倒是现实却也存在很多问题:
针对以上 第二个问题,也就是我这篇文章的主要面对的问题,不管是先写库还是先删除数据在写库,还是先删除数据然后写库然后再删除,都存在数据不一致的情况,因为在高并发的场景下,写和读是高频率并发的,你无法提前预知谁先到来。针对这一问题,目前业界有一下四个解决方案:
public void updateUserInfo(String key,UserBasic userBasic){
redis.delKey(userBasic.getUserid());
userBasicMapper.update(userBasic);
Thread.sleep(200);
redis.delKey(userBasic.getUserid())
}
这种方式,在一定程度上能够解决数据一致问题,在数据库I/O写入完成之后再次清理缓存,能够让最新的数据以最短的时间同步的缓存中去,在写数据库期间的读请求还是会打到数据中中,存在两个明显的问题:1,200毫秒怎么来的,主要考虑数据库主从同步时间,或者直接从主库读取缓存数据;2,清空缓存之后,高并发操作mysql存在缓存击穿的风险。
public void updateUserInfo(String key,UserBasic userBasic){
redis.del(userBasic.getUserid());
boolean success = userBasicMapper.update(data);
if(success){
redis.put("newdata",userBasic,200);
}
new Thread(new Runnable() {
@Override
public void run() {
Thread.sleep(200);
redis.delKey(userBasic.getUserid())
}
})
}
对于以上数据一致性解决方案,第四方案是最优选,在数据库主库操作没返回前,不清理缓存,以为这个时候数据库数据还没更新,和缓存的旧数据是一致的。主库更新完成之后,暂时使用操作数据更新缓存,确保了缓存数据和主库数据一致。在主从同步之后再异步更新缓存,确保了缓存和更新了数据之后的从库数据一致。比较完美的解决了以上问题。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。