作者:翁志华来源:https://www.cnblogs.com/wzh2010/概述我们说的缓存分为进程内部缓存(系统内部缓存)和缓存服务(如redis/memcache)。计算机服务从原来的单一结构,到多实例,再到现在流行的微服务,缓存服务也越来越流行。进程缓存先说进程缓存,存储站点和服务进程中的数据。在Web的发展史上,这种方式一直很流行。比如早期常用的.Net的System.Web.Caching。这个实现载体很简单,比如一个带锁的HasTable,或者一个List对象。使用简单方便,可以存储数据、html页面片段、文件,甚至任何对象。在单体结构的Web模式下,将进程内缓存发展到极致,大致流程如下:相比原来没有缓存,进程内缓存的优势在于数据读取不再直接访问数据库。存在,存在则直接读取,不存在则从数据库中取出,同时写入缓存。这样就避免了每次请求都去数据库,减少了网络开销和数据请求次数,提高了数据获取的效率,基本相当于在内存中执行。缓存的目的是隔离冷热数据。对于频繁修改的数据,缓存意义不大,比如微信用户的实时步数。更有价值的是那些不经常修改且数据量大的,比如系统字典和配置数据。判断是否创建缓存需要一定的依据。以下是我团队的攻略,不一定适用。可以参考:缓存的必要性:数据是否变化太频繁,可能导致缓存不断重建,降低效率。评估方法:在缓存有效期内未主动更新的量应超过60%。假设缓存时间:3600s假设同类型缓存数据库:60006000*60%=3600一个小时内数据没有更新,这样的缓存更有价值。进程缓存的问题在互联网大潮下。随着用户数量的迅速增加,原来单一的结构逐渐发展为Web服务集群。在多实例目标下,进程缓存的劣势越来越明显。比如缓存不能统一。如果站点和服务中的多个节点访问一个统一的缓存服务(如redis或memerche),数据统一存储,数据的一致性更容易保证。但是如果是进程缓存,数据存储在站点和服务的多个节点,每个节点都有一个缓存,存储多份,很难保证一致性。如上图所示,但是有问题。Cache1、Cache1、Cache3的一致性很难保证。如果要保持缓存的一致性,应该怎么做呢?一般有以下几种方式:1、单个服务节点通知其他服务节点。如果我们只在WebService1执行业务操作时修改数据库和更新缓存,同时通知其他WebService服务,当其他WebService收到信息时,再做一次缓存更新。2、启动MQ通知其他节点:如下图,可以通过MQ通知其他节点。写入请求发生在server1上。修改自己的缓存数据和数据库中的数据后,通知MQ生产数据变化。server2和server1订阅MQ消息。在消费MQ信息时,它们也会修改缓存的数据。3、和WebServer的关系解耦有一个简单的方法,就是直接放弃“实时一致性”,开启一个独立的进程服务,定时从后端拉取最新数据,更新内存缓存。为了保持数据的一致性,上述方法增加了一定的开销。一方面,缓存数据同步过程中存在出错风险;另一方面,它实际上违背了缓存的原则:冷热数据隔离,有效利用冷数据降低数据库压力,提高效率。如果缓存经常被修改或同步,那么缓存的价值就不是很大。补充:1和2两种方法中,实例越多,缓存冗余越多,越难保证各缓存节点数据同步的原子性,越难保证一致性。第三种方式:使用时序拉取本身已经放弃了数据的实时一致性。所以我们在以下几种情况下放弃进程缓存而选择缓存服务:1、web集群下,存在多个实例,业务数据不一致是不允许的(相信大部分业务是不允许的)2.In-processcache数据量大,缓存内存空间不足,影响web性能。可以考虑使用缓存服务(redis等缓存服务,一般都是独立服务甚至集群配置,支持超大规模)。3.评估value大小、缓存内存空间、峰值QPS、过期时间、缓存命中率、读写更新策略、key值分发路由策略、过期策略、数据一致性方案,根据判断是否使用缓存服务到实际需要。缓存服务在互联网分层架构中,最常用的KV结构缓存是redis。它具有以下特点:1.支持字符串、哈希、列表、集合、有序集合等复杂数据结构。支持客户订单信息列表、用户留言、发表评论等多种场景。2、支持持久化首先,redis的所有数据都保存在内存中,然后时不时的异步保存到磁盘(这叫“半持久化模式”);也可以在每次数据变化时写入一个appendonlyfile(aof)(这叫“全持久化模式”,效率会低一些)。但是我们尽量不要使用redis作为数据库。如果确实需要持久化数据,推荐使用MySQL:2.1。redis的定期快照并不能保证数据不丢失。2.2.redis的AOF会降低效率,不能支持太大3.高可用。Redis天然支持集群功能,可以实现主动复制和读写分离。官方还提供了哨兵集群管理工具,可以实现主从服务监控和故障自动转移。4、存储内容比较大String类型:String类型的一个值最多可以存储512M,List、Set、Hash类型:一个列表的元素个数最多为2^32-1,即4294967295个。5.支持事务操作是原子的,所有对数据的改变要么执行要么根本不执行。避免业务数据不一致。缓存使用注意事项1、web服务单机模式转为多实例后,我们将进程缓存升级为缓存服务(redis),清理所有缓存使用,改为与redis对接。但是有一些地方漏掉了,因为我们有3个实例,所以漏掉的那几个地方,一旦某个数据被修改了,一会儿是新值,一会儿是旧值,这是惊人的。2.谨防缓存崩溃和雪崩。我们对此有过惨痛的教训。我们将在后续文章中进行分析。近期热点文章推荐:1.1,000+Java面试题及答案(2021最新版)2.终于通过开源项目拿到了IntelliJIDEA激活码,太贴心了!3、阿里Mock工具正式开源,秒杀市面上所有Mock工具!4、SpringCloud2020.0.0正式发布,全新颠覆版本!5.《Java开发手册(嵩山版)》最新发布,赶快下载吧!感觉不错,别忘了点赞+转发!
