- 可视化管理工具redis-desktop-manager安装与配置
1.1 双击redis-desktop-manager-0.8.8.384.exe即可1.2 配置远程登录
vi redis.conf #编辑redis.conf文件
命令模式下输入“/字符串”,例如:“/requirepass”,再按N键向下查找1)修改访问IP地址,服务器IP(69)
#bind 127.0.0.1 #注释这一行2)找到下面这一行并去除注释,并添加密码(396行)
#requirepass foobared #修改前
requirepass 123456 #修改后3)配置redis的6379端口到防火墙
firewall-cmd --zone=public --add-port=6379/tcp --permanent &&
firewall-cmd --reload &&
firewall-cmd --list-ports Java访问redis
2.1 添加依赖<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency>
2.2 Java连接redis
Jedis jedis = new Jedis(ip, port); jedis.auth("123456");//权限认证 jedis.ping(); jedis.select(0);//切换数据库
2.3 Java操作redis
string(字符串)
hash(哈希)
list(列表)
set(集合)
zset(sorted set:有序集合)
zadd/zrevrange
注1:不需要记得API的方法,只需要查redis命令
spring+redis集成配置
jedis.zadd("zset", 50d, "zs");
jedis.zadd("zset", 30d, "lw");
jedis.zadd("zset", 100d, "ww");
ScanResult zscan = jedis.zscan("zset", 0);
List result1 = zscan.getResult();
for (Tuple tuple : result1) {
System.out.println(tuple.getScore()+","+tuple.getElement());
}
- 前提
spring+redis集成已完成 spring注解式缓存使用步骤
1.0 前提:spring+redis集成已完成1.1 配置缓存管理器
<bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"> <constructor-arg name="redisOperations" ref="redisTemplate" /> <!--redis缓存数据过期时间单位秒--> <property name="defaultExpiration" value="${redis.expiration}" /> <property name="usePrefix" value="true"/> <property name="cachePrefix"> <bean class="org.springframework.data.redis.cache.DefaultRedisCachePrefix"> <constructor-arg index="0" value="-cache-"/> </bean> </property>
1.2 配置自定义Key生成器CacheKeyGenerator
缓存的Java对象一定要重写hashCode和eqauls <bean id="cacheKeyGenerator" class="com.zking.ssm.redis.CacheKeyGenerator"></bean>
1.3 启用缓存注解功能
<cache:annotation-driven cache-manager="redisCacheManager" key-generator="cacheKeyGenerator"/>
1.4 在需要的地方进行注解缓存
缓存注解
2.1 @CacheConfig它是一个类级别的注解,允许共享缓存的名称、KeyGenerator、CacheManager和CacheResolver value:缓存位置的一段名称,不能为空 key:缓存的key,默认为空,表示使用方法的参数类型及参数值作为key,支持SpEL
2.2 @Cacheable
配置在方法或类上,作用:本方法执行后,先去缓存看有没有数据,如果没有,从数据库中查找出来,给缓存中存一份,返回结果, 下次本方法执行,在缓存未过期情况下,先在缓存中查找,有的话直接返回,没有的话从数据库查找 value:缓存位置的一段名称,不能为空 key:缓存的key,默认为空,表示使用方法的参数类型及参数值作为key,支持SpEL keyGenerator:指定key的生成策略 condition:触发条件,满足条件就加入缓存,默认为空,表示全部都加入缓存,支持SpEL 注1:condition是在方法执行前评估, unless是在方法执行后评估.
2.3 @CachePut
类似于更新操作,即每次不管缓存中有没有结果,都从数据库查找结果,并将结果更新到缓存,并返回结果 value 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 key 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 condition 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存
2.4 @CacheEvict
用来清除用在本方法或者类上的缓存数据(用在哪里清除哪里) value:缓存位置的一段名称,不能为空 key:缓存的key,默认为空,表示使用方法的参数类型及参数值作为key,支持SpEL condition:触发条件,满足条件就加入缓存,默认为空,表示全部都加入缓存,支持SpEL allEntries:true表示清除value中的全部缓存,默认为false
Spring-Cache key设置
3.1 基本形式@Cacheable(value="cacheName", key="#id") public ResultDTO method(int id); 注1:Spring Cacheable注解不缓存null值 用Cacheable注解时,发现空值,也会被缓存下来。下次另一个系统如果更新了值,这边从缓存取,还是空值,会有问题。 解决方案: @Cacheable(value = "service", key = "#service.serviceId.toString()", unless = "#result == null") @Cacheable(value = "service", keyGenerator = RedisKeys.KEY_GENERATOR, unless = "#result.size() == 0")
3.2 组合形式
@Cacheable(value="cacheName", key="T(String).valueOf(#name).concat('-').concat(#password)) public ResultDTO method(int name, String password);
3.3 对象形式
@Cacheable(value="cacheName", key="#user.id) public ResultDTO method(User user); 注1:以上三种配置方式中,使用了spEL表达式
3.4 自定义Key生成器
@Cacheable(value="gomeo2oCache", keyGenerator = "keyGenerator") public ResultDTO method(User user); spring注解式缓存中的巨坑~~~~~~~ 没有指定key,默认情况下spirng会使用SimpleKeyGenerator生成key, 而Spring默认的SimpleKeyGenerator是不会将函数名组合进key中的,举个例子: @Component public class CacheTestImpl implements CacheTest { @Cacheable("databaseCache") public Long test1() { return 1L; } @Cacheable("databaseCache") public Long test2() { return 2L; } @Cacheable("databaseCache") public Long test3() { return 3L; } @Cacheable("databaseCache") public String test4() { return "4"; }//注意返回的是字符串“4” } 我们期望的输出是: 1 2 3 4 而实际上的输出是: 1 1 1 ClassCastException: java.lang.Long cannot be cast to java.lang.String
此外,原子类型的数组,直接作为key使用也是不会生效的,为了解决上述2个问题,只能通过自定义KeyGenerator解决
自定义Key生成器CacheKeyGenerator:源码见资料“CacheKeyGenerator.java”,另外此类使用非加密哈希算法MurmurHash
(源码46行: Hashing.murmur3_128().hashString),需要引入google guava项目,其pom如下:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0.1-jre</version>
</dependency>
- redis缓存的一些注意事项
只应将热数据放到缓存中
所有缓存信息都应设置过期时间
缓存过期时间应当分散以避免集中过期
缓存key应具备可读性
应避免不同业务出现同名缓存key
可对key进行适当的缩写以节省内存空间
选择合适的数据结构
确保写入缓存中的数据是完整且正确的
避免使用耗时较长的操作命令,如:keys *
Redis默认配置中操作耗时超过10ms即视为慢查询
一个key对应的数据不应过大对于string类型,一个key对应的value大小应控制在10K以内,1K左右更优hash类型,不应超过5000行
避免缓存穿透
数据库中未查询到的数据,可在Redis中设置特殊标识,以避免因缓存中无数据而导致每次请求均达到数据库缓存层不应抛出异常
缓存应有降级处理方案,缓存出了问题要能回源到数据库进行处理
可以进行适当的缓存预热
对于上线后可能会有大量读请求的应用,在上线之前可预先将数据写入缓存中
读的顺序是先缓存,后数据库;写的顺序是先数据库,后缓存
数据一致性问题
数据源发生变更时可能导致缓存中数据与数据源中数据不一致,应根据实际业务需求来选择适当的缓存更新策略:
主动更新:在数据源发生变更时同步更新缓存数据或将缓存数据过期。一致性高,维护成本较高。
被动删除:根据缓存设置的过期时间有Redis负责数据的过期删除。一致性较低,维护成本较低。
- 根据用户ID或公司ID进行查询(此想法未测试)
@Transactional(readOnly = true)
@Cacheable(value = "service+'By'+service.userId", unless = "#result.size() == 0")
List listByUserId(Service service, PageBean pageBean);