大型高并发与高可用缓存架构总结

数据库和redis缓存双写不一致的问题

    最初级的缓存不一致问题以及解决方案
    Q:若是先修改数据库再删除缓存,那么当缓存删除失败来,那么会致使数据库中是最新数据,缓存中依旧是旧数据,形成数据不一致。

     A:能够先删除缓存,再修改数据库,若是删除缓存成功可是数据库修改失败,那么数据库中是旧数据,缓存是空不会出现不一致

    比较复杂的数据不一致问题分析
    问题:对于数据发生来变动,先删除缓存,而后去修改数据库,此时数据库中的数据尚未修改为功,并发的读请求到来去读缓存发现是空,进而去数据库查询到此时的旧数据放到缓存中,而后以前对数据库数据的修改为功来,就会形成数据不一致

    解决方案:将数据库与缓存更新与读取操做进行异步串行化。当更新数据的时候,根据数据的惟一标识,将更新数据操做路由到一个jvm内部的队列中,一个队列对应一个工做线程,线程串行拿到队列中的操做一条一条地执行。当执行队列中的更新数据操做,删除缓存,而后去更新数据库,此时尚未完成更新的时候过来一个读请求,读到了空的缓存那么能够先将缓存更新的请求发送至路由以后的队列中,此时会在队列积压,而后同步等待缓存更新完成,一个队列中多个相同数据缓存更新请求串在一块儿是没有意义的,所以能够作过滤处理。等待前面的更新数据操做完成数据库操做以后,才会去执行下一个缓存更新的操做,此时会从数据库中读取最新的数据,而后写入缓存中,若是请求还在等待时间范围内,不断轮询发现能够取到缓存中值就能够直接返回(此时可能会有对这个缓存数据的多个请求正在这样处理);若是请求等待事件超过必定时长,那么这一次的请求直接读取数据库中的旧值

    对于这种处理方式须要注意一些问题:
        读请求长时阻塞:因为读请求进行来很是轻度的异步化,因此对超时的问题须要格外注意,超过超时时间会直接查询DB,处理很差会对DB形成压力,所以须要测试系统高峰期QPS来调整机器数以及对应机器上的队列数最终决定合理的请求等待超时时间
        多实例部署的请求路由:可能这个服务会部署多个实例,那么必须保证对应的请求都经过nginx服务器路由到相同的服务实例上
        热点数据的路由导师请求的倾斜:由于只有在商品数据更新的时候才会清空缓存,而后才会致使读写并发,因此更新频率不是过高的话,这个问题的影响并非特别大,可是的确可能某些机器的负载会高一些 。nginx