微服务架构中的缓存技术:SpringBoot 中缓存自动配置原理详解并整合 Redis
JSR107
Java Caching 定义 5 个核心接口:CachingProvider,CacheManager,Cache,Entry,Expiry
CachingProvider:定义了创建,配置,获取,管理和控制多个 CacheManager.一个应用可以在运行期间访问多个 CachingProvider
CacheManager:定义了创建,配置,获取,管理和控制多个唯一命名的 Cache,这些 Cache 存在于 CacheManager 的上下文中,一个 CacheManager 仅被一个 CacheProvider 所拥有
Cache:是一个类似 Map 的数据结构并临时存储以 key 为索引的值,一个 Cache 仅被一个 CacheManager 所拥有
Entry:是一个存储在 Cache 中的 key-value 键值对
Expiry:每一个存储在 Cache 中的条目有一个定义的有效期,一旦超过这个时间,条目为过期状态.一旦过期,条目将不可访问,更新和删除.缓存有效期可以通过 ExpiryPolicy 设置
搭建缓存基本环境
缓存的使用
步骤
缓存重要概念
Cache: 缓存接口,定义缓存操作.实现有:RedisCache,EhCacheCache,ConcurrentMapCache 等
CacheManager: 缓存管理器,管理各种缓存组件
keyGenerator: 缓存数据时 key 生成策略
serialize: 缓存数据时 value 序列化策略
缓存注解
@Cacheable: 主要针对方法配置,根据方法的请求参数对结果进行缓存:以后再要相同的数据,直接从缓存中获取,不再调用方法
@CacheEvict: 清空缓存
@CachePut: 保证方法被调用,结果被缓存,更新缓存数据
@EnableCaching: 开启基于注解的缓存
缓存的工作原理
默认使用的是 ConcurrentMapCache 组件中的 CacheManager 进行缓存的,将数据保存在 ConcurrentMap<object,object>中
自动配置类
缓存配置类
默认 SimpleCacheConfiguration 生效:
1.给容器中注册 CacheManager:ConcurrentMapCacheManager
2.ConcurrentMapCacheManager 可以获取和创建 ConcurrentMapCache 类型的缓存组件 3.ConcurrentMapCache 的作用是将数据保存在 ConcurrentMap 中
缓存的运行流程
@Cacheable
方法运行之前,CacheManager 先获取相应的缓存,按照 CacheNames 指定的名字获取,,第一次获取缓存如果没有 Cache 组件会自动创建缓存组件
在 Cache 中使用 key 查找缓存内容,key 是通过 KeyGenerator 生成的,默认就是方法的参数
@Cacheable 标注的方法执行之前先检查缓存中是否有缓存数据,默认按照参数值作为 key 去查询缓存,如果没有就运行方法,并将结果放入缓存中
流程核心:
使用 CacheManager(ConcurrentMapCacheManager)按照 CacheNames 指定的名字获取 Cache(ConcurrentMapCache)组件
key 是使用 keyGenerator 生成的,默认使用 SimpleKeyGenerator 生成 key
@CachePut 既调用方法,又更新缓存数据(对数据库修改操作,会将结果保存在缓存中)
运行流程:
先调用目标方法
再将方法的结果放到缓存中
@CacheEvict 清空缓存:当数据库中数据被删除时,执行删除缓存中的数据
通过 key 指定要清楚的缓存数据
allEntries: 是否清除这个缓存中所有数据
beforeInvocation: 是否在方法执行之前清除缓存中的数据
@Caching
定义复杂的缓存规则
如果在定义的复杂缓存规则中有 @CachePut 或则 @CacheEvict(beforInvocation=true) ,这个注解就是在目标方法执行后执行
@CacheConfig
配置缓存中的所有的公共配置
缓存中间件 Redis
Redis: Redis 是一个开源的内存中的数据结构存储系统,可以用作数据库,缓存和消息中间件
操作工具:Redis Desktop Manager
Redis 配置
启动 Redis 服务端:
直接双击 redis-server.exe 文件
或者在命令行中输入 start redis-server.exe
启动 Redis 客户端:
启动 Redis 服务端完成之后
直接双击 redis-cli.exe 文件
或者在命令行输入 start redis-cli.exe
设置 Redis 密码:
命令方式:
获取旧密码 : config get requirepass
设置新密码 : config set requirepass
config 文件方式:
打开配置文件 redis.windows.conf
修改配置文件中的 reqiurepass
整合 Redis 缓存
在 pom.xml 中引入 redis 依赖
配置 redis,在 application.properties 中配置 redis
RedisTemplate:(操作 k-v 都是对象)
保存对象时,默认使用的是 JDK 的序列化机制,将序列化后的数据保存到 redis 中
为了增强 Redis 数据库中的数据可读性:
将对象数据以==json==方式保存:
将对象转化为 json
配置 redisTemplate 的 json 序列化规则,使用 Jackson2JsonRedisSerializer 进行数据的序列化
StringRedisTemplate(操作 k-v 都是字符串)在 RedisAutoConfiguration 中:
在 StringRedisTemplate 中:
Redis 服务治理
Redis 默认是惰性删除:
过期的 Redis 的不会删除
获取 key 时会检查 key 是否有效,如果无效才会删除
Redis 的惰性删除机制会造成 Redis 缓存中保存很多过期的 key. 可以使用定时删除过期的 key 的策略解决
缓存雪崩
缓存雪崩: 同一时刻 redis 的 key 全部失效
解决方案: 给 Redis 的过期时间设置为随机
缓存击穿
缓存击穿: 同一时刻缓存中没有数据,请求转向数据库
解决方案:
第一次请求如果没有数据,直接返回空
然后发送一个消息队列进行数据库同步
第二次请求再从缓存中获取数据
自定义 CacheManager
CacheManagerCustomizers: 定制缓存规则
可以在方法中使用缓存管理器获取缓存,调用操作 API 对缓存中的数据进行操作
版权声明: 本文为 InfoQ 作者【攻城狮Chova】的原创文章。
原文链接:【http://xie.infoq.cn/article/df1fd2806d9a772ad60b3bbbb】。文章转载请联系作者。
评论