1
考虑数据不一致性容忍度
当我们采取数据放在redis和放在数据库的时候就意味着我们允许了数据在某一时刻处于不一致的情况,除非我们采取只读写数据库或者只读写redis这样单一数据源读写的方式,否则考虑系统异常,基本没法100%保证两边数据一致,所以延迟只能降低,很难完全消除。
保证他们的一致性也类似于分布式事务的处理,最终目的都是保证不同系统的状态一致性。
2
redis只读,数据更新时只删除redis,数据增加不需要对redis操作,在查询时从库查最新值
2 .1 数据库更新同步删除redis
先删除后更新库,需考虑删除后另外线程马上查询数据就会在数据库更新前查到就数据。可以在更新库后 sleep一段时间或延迟异步机制再次清除redis
先更新数据库在清除key,清除key之前其他线程查询redis会有旧数据,但很快就会被清除,且清除后不存在上面的查库查到旧数据的情况。
2.2 更新数据库后异步删除redis
设计简单,采用异步消息机制或数据监听可在redis操作失败时通过重试达到最终一致。
2.3 改进措施
要进一步降低延迟的话可联合同步和异步操作,更新数据库之后同步清除,这样异步更新的操作就相当于同步清除出错时的补偿操作,在系统稳定时可保证大部分时间延迟基本可以忽略
3
redis可写,不用更新后查询再从库里查
3.1 同步写库
先写redis后写库,库写失败的话,可try catch 异常来在库写失败时同步回滚redis。可由于缺少可靠存储介质,若发生系统意外宕机或者redis回滚写失败就无法马上进行redis回滚,可会导致redis数据在未自动过期前较长时间不一致。
先写库,后写redis,可减少因库写失败导致的事务回滚,可需要对redis写入失败进行处理。方案有如下
1 此时数据库事务未提交,可抛异常,回滚数据库
2 事务已提交,可降级处理为发消息或监听binlog交由异步线程对redis数据进行补偿写入。
3.2 redis可写,异步写库
1 性能最好,因为只有redis操作,同时稳定性最差,因为redis故障,系统宕机,未及时写库,会让数据丢失,库里缺少最新数据
改进 :
redis写入的时候,数据库insert变化记录,后面数据库再根据变化记录去执行update操作,可牺牲一部分性能,提升稳定可靠性.至于redis和数据记录insert的一致性就和上面讲的同步写库一样了。
总结
综合来讲,简单方便可靠的是写库的同时同步删除key,再运用分布式事务的补偿思想增加数据监听进行补偿操作。讲究高性能的可采用redis可写,异步写库的方式,此时库的数据更像是一种延迟快照备份。