微服务架构下静态数据通用缓存机制
持久化是为了解决网络抖动或者崩溃导致数据丢失的问题,在数据从业务服务到队列,队列自身处理,再从队列到缓存处理程序,中间都可能丢失数据。为了解决丢失数据的问题,需要发送时确认、队列自身持久化、接收时确认;但是需要注意确认机制可能会导致重复数据的产生,因为在未收到确认时就需要重新发送或接收,而数据实际上可能被正常处理,只是确认丢失了;确认机制还会降低队列的吞吐量,但是根据我们的定义业务静态数据的变更频率应该不高,如果同时还需要较高的并发分片是个不错的选择。 这里持久化队列推荐选择RabbitMQ,虽然吞吐量支持的不是很大,但是各方面综合不错,并发够用就好。 为什么需要数据一致检查程序? 在业务服务操作完关系数据库后,数据发送到队列之前(或者不用队列就是直接写入缓存之前),业务服务崩溃了,这时候数据就不能更新到缓存了。还有一种情况是Redis发生了故障转移,master中的更新没有同步到slaver。通过引入这么一个检查程序,定时的检查关系数据库数据和缓存数据的差别,如果缓存数据比较陈旧,则更新之。这样提供了一种极端情况下的挽救措施。 这个检查程序的运行频率需要综合考虑数据库压力和能够承受的数据陈旧时间,不能把数据库查死了,也不能陈旧太久导致大量数据不一致。可以通过设置上次检查时间点的方式,每次只检查从上次检查时间点(或者最近几次,防止Redis故障转移数据未同步的问题)到本次检查时间点发生变更的数据,这样每次检查只对增量变更,效率更高。 同时需要理解在分布式系统中,微服务架构下,数据不一致是经常出现的,必须在一致性和可用性之间做出权衡,尽力去降低影响,比如使用准实时或最终一致性。 只要数据一致检查程序是不是就够了? 假设没有缓存处理程序,通过定时同步关系数据库和缓存数据库是不是就够了呢?这还是取决于业务,如果是车型库这种数据,增加一个新的车型,本来之前就没有,时间上并不是很敏感,这个是可以的。但是对于新增了用户或者车辆,数据消费者还是希望能够马上使用最新的数据进行处理,越快越好,这时使用同步或者准同步更新就能更加贴近需求。Java架构交流学习圈:874811168 面向1-3年经验 Java开发人员 帮助突破瓶颈 提升思维能力 为什么不用缓存过期机制? 使用缓存过期机制可以不需要缓存处理程序和数据一致检查程序,业务服务首先从Redis查询数据,如果数据存在就直接返回,如果不存在则从关系数据库查询,然后写入Redis,然后再返回,这也是一种常用的缓存处理机制,网上可以查询到很多,很多人用的也很好。 但是缓存的过期时间是个问题:缓存多长时间过期,设置的短可以降低数据的陈旧,但是会增加缓存穿透的概率,即使采用随机的缓存过期时间,在Redis重启或者故障转移的情况下还是会可能导致缓存雪崩,雪崩的情况下采用数据预热机制,也可能会导致服务更长时间的不可用;设置的长可以提升缓存的使用率,但是增加了数据陈旧,在上边对静态数据的定义中对其准确率和实时性都有较高的要求,业务上能不能接受需要考虑。而且如果操作数据和查询存在波动的峰谷,是不是要引入动态TTL的机制,以达到缓存使用和直接访问数据库的一种平衡,这就需要权衡业务需求和技术方案。 总结 通过上边的这些问题问答,再来看看上面提出的微服务架构下静态数据通用缓存处理机制。
对于微服务架构而言,这个机制借助队列这种通用的解耦方式,独立了缓存更新处理,通过准实时更新和定时检查,保证了缓存的实时性和极端情况下较短时间内达到最终一致,通过缓存的持久化机制消除了缓存穿透和雪崩,在缓存的数据较大或读取并发较高时支持水平扩容,可以认为对业务静态数据提供了一种广泛适用的缓存处理机制。 这个方案在某些情况下可能是没有必要的,比如你要缓存一个全国限行的城市列表,使用一个进程内缓存就够了。 最后剩下的就是工作量的问题了,这个会给开发和维护带来复杂性,队列有没有用的顺手的,人手是不是够,业务需求是什么样的,需要考虑清楚。 【编辑推荐】
点赞 0 (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |