redis和数据库一致性问题

redis和数据库一致性问题

1.保证redis和数据库数据一致性,一般采取最终一致性做法。如果要强一致性,这个性能基本就不行了。

redis 没有缓存更新命令,倒是可以用添加命令对value进行覆盖。不过我们一般不这样做。

因为比如一个缓存1分钟跟新100次,这个时候redis也会更新100次,可是我这1分钟的读请求可能就1次,更新100次显然损耗过多的性能。

所以我们采用删除缓存的做法,读数据的时候,第一次从数据库查出数据,然后缓存进redis就好。

2.这个时候出现了一个问题,先删缓存再跟新数据库,还是先跟新数据库再删缓存。

删除缓存 + 更新数据库

会出现问题:比如我A请求过来发现缓存没有,然后去数据库查出来了数据 1,这个时候要把缓存写进redis,还没写进redis时,B请求更新了数据库,他删缓存,跟新数据库为2。B请求结束之后我A请求才把结果1写进redis,这就会造成redis是1,数据库是2的情况。

更新数据库+删除缓存

会出现问题:比如我A线程读数据为1,准备写1进缓存,还没来得及写,B线程跟新数据库为2,删缓存,然后A线程再写1进缓存,也是一样会出现数据不一致的情况。

延迟双删:解决上述问题

先删缓存,修改数据库,然后异步线程延迟一段时间后再删缓存。

3.除了上述方案后,我们还可以用日志方式

我们来分析一波数据库读写分离架构,主节点写数据,从节点通过binlog日志来同步数据

主从复制的原理

①当Master节点进行insert、update、delete操作时,会按顺序写入到binlog中。

②salve从库连接master主库,Master有多少个slave就会创建多少个binlog dump线程。

③当Master节点的binlog发生变化时,binlog dump 线程会通知所有的salve节点,并将相应的binlog内容推送给slave节点。

④I/O线程接收到 binlog 内容后,将内容写入到本地的 relay-log。

⑤SQL线程读取I/O线程写入的relay-log,并且根据 relay-log 的内容对从数据库做对应的操作。

使用阿里Canal,官网地址(https://github.com/alibaba/canal)

canal是通过模拟成为mysql 的slave的方式,监听mysql 的binlog日志来获取数据,binlog设置为row模式以后,不仅能获取到执行的每一个增删改的脚本,同时还能获取到修改前和修改后的数据,基于这个特性,canal就能高性能的获取到mysql数据数据的变更。

使用canal注意事项

①一定要确保mysql的binlog模式为row模式,canal原理是解析Binlog文件,并且直接中文件中获取数据的。

②redis的持久化机制可以关闭了,rdb aof都不需要,以此来提高性能

 

posted @ 2022-05-12 17:05  java架构师1  阅读(261)  评论(0)    收藏  举报