北京礼品网站建设,wordpress 文章预览,安卓定制v,网络广告策划的步骤在做系统优化时#xff0c;想到了将数据进行分级存储的思路。因为在系统中会存在一些数据#xff0c;有些数据的实时性要求不高#xff0c;比如一些配置信息。基本上配置了很久才会变一次。而有一些数据实时性要求非常高#xff0c;比如订单和流水的数据。所以这里根据数据… 在做系统优化时想到了将数据进行分级存储的思路。因为在系统中会存在一些数据有些数据的实时性要求不高比如一些配置信息。基本上配置了很久才会变一次。而有一些数据实时性要求非常高比如订单和流水的数据。所以这里根据数据要求实时性不同将数据分为三级。第1级订单数据和支付流水数据这两块数据对实时性和精确性要求很高所以不添加任何缓存读写操作将直接操作数据库。第2级用户相关数据这些数据和用户相关具有读多写少的特征所以我们使用redis进行缓存。第3级支付配置信息这些数据和用户无关具有数据量小频繁读几乎不修改的特征所以我们使用本地内存进行缓存。但是只要使用到缓存无论是本地内存做缓存还是使用 redis 做缓存那么就会存在数据同步的问题因为配置信息缓存在内存中而内存时无法感知到数据在数据库的修改。这样就会造成数据库中的数据与缓存中数据不一致的问题。接下来就讨论一下关于保证缓存和数据库双写时的数据一致性。解决方案那么我们这里列出来所有策略并且讨论他们优劣性。先更新数据库后更新缓存先更新数据库后删除缓存先更新缓存后更新数据库先删除缓存后更新数据库先更新数据库后更新缓存这种场景一般是没有人使用的主要原因是在更新缓存那一步为什么呢因为有的业务需求缓存中存在的值并不是直接从数据库中查出来的有的是需要经过一系列计算来的缓存值那么这时候后你要更新缓存的话其实代价是很高的。如果此时有大量的对数据库进行写数据的请求但是读请求并不多那么此时如果每次写请求都更新一下缓存那么性能损耗是非常大的。举个例子比如在数据库中有一个值为 1 的值此时我们有 10 个请求对其每次加一的操作但是这期间并没有读操作进来如果用了先更新数据库的办法那么此时就会有十个请求对缓存进行更新会有大量的冷数据产生如果我们不更新缓存而是删除缓存那么在有读请求来的时候那么就会只更新缓存一次。先更新缓存后更新数据库这一种情况应该不需要我们考虑了吧和第一种情况是一样的。先删除缓存后更新数据库该方案也会出问题具体出现的原因如下。此时来了两个请求请求 A(更新操作) 和请求 B(查询操作)请求 A 会先删除 Redis 中的数据然后去数据库进行更新操作此时请求 B 看到 Redis 中的数据时空的会去数据库中查询该值补录到 Redis 中但是此时请求 A 并没有更新成功或者事务还未提交那么这时候就会产生数据库和 Redis 数据不一致的问题。如何解决呢其实最简单的解决办法就是延时双删的策略。但是上述的保证事务提交完以后再进行删除缓存还有一个问题就是如果你使用的是 Mysql 的读写分离的架构的话那么其实主从同步之间也会有时间差。此时来了两个请求请求 A(更新操作) 和请求 B(查询操作)请求 A 更新操作删除了 Redis请求主库进行更新操作主库与从库进行同步数据的操作请 B 查询操作发现 Redis 中没有数据去从库中拿去数据此时同步数据还未完成拿到的数据是旧数据此时的解决办法就是如果是对 Redis 进行填充数据的查询数据库操作那么就强制将其指向主库进行查询。先更新数据库后删除缓存问题这一种情况也会出现问题比如更新数据库成功了但是在删除缓存的阶段出错了没有删除成功那么此时再读取缓存的时候每次都是错误的数据了。此时解决方案就是利用消息队列进行删除的补偿。具体的业务逻辑用语言描述如下请求 A 先对数据库进行更新操作在对 Redis 进行删除操作的时候发现报错删除失败此时将Redis 的 key 作为消息体发送到消息队列中系统接收到消息队列发送的消息后再次对 Redis 进行删除操作但是这个方案会有一个缺点就是会对业务代码造成大量的侵入深深的耦合在一起所以这时会有一个优化的方案我们知道对 Mysql 数据库更新操作后再 binlog 日志中我们都能够找到相应的操作那么我们可以订阅 Mysql 数据库的 binlog 日志对缓存进行操作。总结每种方案各有利弊比如在第二种先删除缓存后更新数据库这个方案我们最后讨论了要更新 Redis 的时候强制走主库查询就能解决问题那么这样的操作会对业务代码进行大量的侵入但是不需要增加的系统不需要增加整体的服务的复杂度。最后一种方案我们最后讨论了利用订阅 binlog 日志进行搭建独立系统操作 Redis这样的缺点其实就是增加了系统复杂度。其实每一次的选择都需要我们对于我们的业务进行评估来选择没有一种技术是对于所有业务都通用的。没有最好的只有最适合我们的。