根据缓存是否与应用进程属于同一进程,可以将内存分为本地缓存和分布式缓存。本地缓存是在同一个进程内的内存空间中缓存数据,数据读写都是在同一个进程内完成;而分布式缓存是一个独立部署的进程并且一般都是与应用进程部署在不同的机器,故需要通过网络来完成分布式缓存数据读写操作的数据传输。
问题:
1.本地缓存应用场景:
a.本地缓存一般适合于缓存只读数据。
b.访问频繁但更新频率低的数据。在程序中,有些表数据,数据很少,但是程序加载的时候要马上访问,并且访问的很 频繁,比如(例如系统配置参数,区域信息),针对这种情况,将数据放到程序的本地缓存中即内存中,从而提升系统的访问效率。
结合前台环境(无关系数据库),本地缓存应用范围较小,一般只用来处理读操作,更新主要靠redis的发布订阅机制和定期失效更新的方式。
2.本地缓存与分布式缓存的特点
本地缓存的特点:
2.1.1 访问速度快,但无法进行大数据存储
本地缓存相对于分布式缓存的好处是,由于数据不需要跨网络传输,故性能更好,但是由于占用了应用进程的内存空间,如 Java 进程的 JVM 内存空间,故不能进行大数据量的数据存储。
2.1.2 集群的数据更新问题
与此同时,本地缓存只支持被该应用进程访问,一般无法被其他应用进程访问,故在应用进程的集群部署当中,如果对应的数据库数据,存在数据更新,则需要同步更新不同部署节点的本地缓存的数据来包保证数据一致性,复杂度较高并且容易出错,如基于 Redis 的发布订阅机制来同步更新各个部署节点。
2.1.3 数据随应用进程的重启而丢失
由于本地缓存的数据是存储在应用进程的内存空间的,所以当应用进程重启时,本地缓存的数据会丢失。所以对于需要持久化的数据,需要注意及时保存,否则可能会造成数据丢失。
分布式缓存的特点:
2.2.1 支持大数据量存储,不受应用进程重启影响
分布式缓存由于是独立部署的进程,拥有自身独立的内存空间,不会受到应用进程重启的影响,在应用进程重启时,分布式缓存的数据依然存在。同时对于数据量而言,由于不需要占用应用进程的内存空间,并且一般支持以集群的方式拓展,故可以进行大数据量的数据缓存。
2.2.2 数据集中存储,保证数据一致性
当应用进程采用集群方式部署时,集群的每个部署节点都通过一个统一的分布式缓存进行数据存取操作,故不存在本地缓存中的数据更新问题,保证了不同节点的应用进程的数据一致性问题。
2.2.3 数据读写分离,高性能,高可用
分布式缓存一般支持数据副本机制,可以实现读写分离,故可以解决高并发场景中的数据读写性能问题。并且由于在多个缓存节点冗余存储数据,提高了缓存数据的可用性,避免某个缓存节点宕机导致数据不可用问题。
2.3.4 数据跨网络传输,性能低于本地缓存
由于分布式缓存是独立部署的进程,并且一般都是与应用进程位于不同的机器,故需要通过网络来进行数据传输,这样相对于本地缓存的进程内部的数据读取操作,性能会较低。
3.如何保证本地缓存和分布式缓存数据的一致性
两种方式
3.1、广播更新策略
使用redis的发布与订阅来实现缓存更新广播,本地缓存存放更新频率低,但请求量很高的数据,对于更新频率很高的数据应该由redis缓存来承担。
当某台服务器的本地缓存更新的时候,通过redis发布与订阅机制发布该key的更新信息,其他服务器监听到key的更新信息则更新本地缓存的key
具体实现
通过注解方式标明该方法时候使用缓存,缓存的超时时间,是否开启本地缓存,如果开启本地缓存则当更新缓存时,先更新本地缓存和redis缓存,然后通过redis发布更新广播,其他服务器接收到该key的更新信息则更新本地缓存
如果添加类型的更新则本地缓存新建key然后查询redis的key将value同步到本地缓存
如果修改类型的更新则查询redis缓存然后将value同步到本地缓存。
如果删除类型的更新则删除本地缓存的key和value。
3.2、定时更新
考虑的本地缓存和服务器缓存要保证数据的一致性,防止因各种原因导致因广播信息没有接收到或者其他原因本地缓存没有更新特加入定时更新策略。
定时更新是在广播更新的基础上在本地缓存加入超时时间,如果超过多长时间没有接收到更新广播,则清除本地缓存的key(设置超时时间),来保证缓存的最终一致性。
缓存注意点
本地缓存必须设置超时时间,必须定时更更新本地缓存,防止因各种原因导致的本地缓存和redis缓存不一致,保证缓存的一致性。
redis缓存不应该设置永久缓存,防止因更新失败导致的缓存不一致,以及僵尸类型的key占用服务器内存(一些系统配置级别的可以设置永久缓存,如系统配置,基本上不会进行更新的或者更新频率很低的)
实现:基于注解
github:
网友评论