这个业务场景,紧张是办理读数据从Redis缓存,一样平常都是按照下图的流程来进行业务操作。

读取缓存步骤一样平常没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就随意马虎涌现缓存(Redis)和数据库(MySQL)间的数据同等性问题。

不管是先写MySQL数据库,再删除Redis缓存;还是先删除缓存,再写库,都有可能涌现数据不一致的情形。
举一个例子:

phpredismysql数据Redis和mysql数据怎么坚持数据一致的 NoSQL

1.如果删除了缓存Redis,还没有来得及写库MySQL,另一个线程就来读取,创造缓存为空,则去数据库中读取数据写入缓存,此时缓存中为脏数据。

2.如果先写了库,在删除缓存前,写库的线程宕机了,没有删除掉缓存,则也会涌现数据不一致情形。

由于写和读是并发的,没法担保顺序,就会涌现缓存和数据库的数据不一致的问题。

如来办理?这里给出两个办理方案,先易后难,结合业务和技能代价选择利用。

缓存和数据库同等性办理方案

1.第一种方案:采取延时双删策略

在写库前后都进行redis.del(key)操作,并且设定合理的超时时间。

代码如下

public void write( String key, Object data ) { redis.delKey( key ); db.updateData( data ); Thread.sleep( 500 ); redis.delKey( key ); }复制代码

2.详细的步骤便是:

先删除缓存再写数据库休眠500毫秒再次删除缓存

那么,这个500毫秒怎么确定的,详细该休眠多久呢?

须要评估自己的项目的读数据业务逻辑的耗时。
这么做的目的,便是确保读要求结束,写要求可以删除读要求造成的缓存脏数据。

当然这种策略还要考虑redis和数据库主从同步的耗时。
末了的的写数据的休眠韶光:则在读数据业务逻辑的耗时根本上,加几百ms即可。
比如:休眠1秒。

3.设置缓存过期韶光

从理论上来说,给缓存设置过期韶光,是担保终极同等性的办理方案。
所有的写操作以数据库为准,只要到达缓存过期韶光,则后面的读要求自然会从数据库中读取新值然后回填缓存。

4.该方案的弊端

结合双删策略+缓存超时设置,这样最差的情形便是在超时时间内数据存在不一致,而且又增加了写要求的耗时。

2、第二种方案:异步更新缓存(基于订阅binlog的同步机制)

1.技能整体思路:

MySQL binlog增量订阅消费+行列步队+增量数据更新到redis

读Redis:热数据基本都在Redis写MySQL:增编削都是操作MySQL更新Redis数据:MySQ的数据操作binlog,来更新到Redis

2.Redis更新

(1)数据操作紧张分为两大块:

一个是全量(将全部数据一次写入到redis)一个是增量(实时更新)

这里说的是增量,指的是mysql的update、insert、delate变更数据。

(2)读取binlog后剖析 ,利用行列步队,推送更新各台的redis缓存数据。

这样一旦MySQL中产生了新的写入、更新、删除等操作,就可以把binlog干系的推送至Redis,Redis再根据binlog中的记录,对Redis进行更新。

实在这种机制,很类似MySQL的主从备份机制,由于MySQL的主备也是通过binlog来实现的数据同等性。

这里可以结合利用canal(阿里的一款开源框架),通过该框架可以对MySQL的binlog进行订阅,而canal正是模拟了mysql的slave数据库的备份要求,使得Redis的数据更新达到了相同的效果。

当然,这里的推送工具你也可以采取别的第三方:kafka、rabbitMQ等来实现推送更新Redis!

末了

后续会持续更新Redis专题知识,写的不好的地方也希望大牛能指示一下,大家以为不错可以点个赞在关注下,往后还会分享更多文章!

欢迎事情一到五年的Java工程师朋友们加入Java进阶高等架构:416843702

群内供应免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,

MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)

合理利用自己每一分每一秒的韶光来学习提升自己,不要再用\"大众没有韶光“来掩饰笼罩自己思想上的