高手的存在,就是让服务10亿人的时候,你感觉只是为你一个人服务......

iBase4J 源码之Redis缓存

目录
  1. 1. 第一步:配置Redis连接池和RedisCacheManager对象
  2. 2. 配置KeyGenerator
  3. 3. 第三步:使用对应的cache注解

Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs and geospatial indexes with radius queries. Redis has built-in replication, Lua scripting, LRU eviction, transactions and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster.

by https://redis.io/


springboot支持的缓存类型有很多

Generic
JCache (JSR-107) (EhCache 3, Hazelcast,Infinispan, etc)
EhCache 2.x
Hazelcast
Infinispan
Couchbase
Redis
Caffeine
Guava (deprecated)
Simple

如果没有显示指明所用的缓存,spring-boot会通过扫描classpath去寻找引入的jar包,并按照上面提到的缓存类型从上到下的优先级,把该类型的缓存作为使用的缓存。

比如在classpath同时扫描到JCache和Redis的jar包,则把JCache作为缓存。


iBase4J采用redis作为缓存服务,配置比较简单,分三个步骤:

第一步:配置Redis连接池和RedisCacheManager对象

iBase4J中的redis.xml集成了Redis连接池、缓存序列化方式、RedisCacheManager对象配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"
xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">

<!-- jedis 配置-->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig" >
<!--最小空闲数-->
<property name="minIdle" value="${redis.minIdle}" />
<!--最大空闲数-->
<property name="maxIdle" value="${redis.maxIdle}" />
<!--最大连接数-->
<property name="maxTotal" value="${redis.maxTotal}" />
<!--最大建立连接等待时间-->
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
<!--是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个-->
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean >
<!-- redisCluster配置 -->
<!-- <bean id="redisClusterConfiguration" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
<constructor-arg name="propertySource">
<bean id="resourcePropertySource" class="org.springframework.core.io.support.ResourcePropertySource"
c:name="redis.properties" c:resource="classpath*:config/system.properties"/>
</bean>
</constructor-arg>
</bean>
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
c:cluster-config-ref="redisClusterConfiguration" c:pool-config-ref="jedisPoolConfig" p:timeout="${redis.timeout}"
p:password="${redis.password}" /> -->

<!-- redis服务器中心 -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.password}"
p:pool-config-ref="jedisPoolConfig" p:timeout="${redis.timeout}" />

<!-- 缓存序列化方式 -->
<bean id="keySerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer" />
<bean id="valueSerializer" class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer" />
<!-- 缓存 -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
<property name="enableTransactionSupport" value="true" />
<property name="keySerializer" ref="keySerializer" />
<property name="valueSerializer" ref="valueSerializer" />
<property name="hashKeySerializer" ref="keySerializer" />
<property name="hashValueSerializer" ref="valueSerializer" />
</bean>
<bean class="org.ibase4j.core.support.cache.RedisHelper" >
<property name="redisTemplate" ref="redisTemplate" />
</bean>
<!-- 缓存管理 -->
<bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
<constructor-arg index="0" ref="redisTemplate" />
<property name="transactionAware" value="true" />
<property name="defaultExpiration" value="${redis.expiration}" />
</bean>
</beans>

配置KeyGenerator

缓存以key-value的形式保存在redis中,可以自定义KeyGenerator来规定想要保存的key的格式。

RedisCacheConfig配置类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
String prefix = Constants.CACHE_NAMESPACE + "M:";

@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
/** 重写生成key方法 */
public Object generate(Object o, Method method, Object... objects) {
StringBuilder sb = new StringBuilder(prefix);
CacheConfig cacheConfig = o.getClass().getAnnotation(CacheConfig.class);
Cacheable cacheable = method.getAnnotation(Cacheable.class);
CachePut cachePut = method.getAnnotation(CachePut.class);
CacheEvict cacheEvict = method.getAnnotation(CacheEvict.class);
if (cacheable != null) {
String[] cacheNames = cacheable.value();
if (ArrayUtils.isNotEmpty(cacheNames)) {
sb.append(cacheNames[0]);
}
} else if (cachePut != null) {
String[] cacheNames = cachePut.value();
if (ArrayUtils.isNotEmpty(cacheNames)) {
sb.append(cacheNames[0]);
}
} else if (cacheEvict != null) {
String[] cacheNames = cacheEvict.value();
if (ArrayUtils.isNotEmpty(cacheNames)) {
sb.append(cacheNames[0]);
}
}
if (cacheConfig != null && sb.toString().equals(prefix)) {
String[] cacheNames = cacheConfig.cacheNames();
if (ArrayUtils.isNotEmpty(cacheNames)) {
sb.append(cacheNames[0]);
}
}
if (sb.toString().equals(prefix)) {
sb.append(o.getClass().getName()).append(".").append(method.getName());
}
sb.append(":");
if (objects != null) {
for (Object object : objects) {
sb.append(JSON.toJSONString(object));
}
}
return sb.toString();
}
};
}
}

第三步:使用对应的cache注解

  1. @Cacheable :主要针对方法配置,能够根据方法的请求参数对其结果进行缓存。

Alt text

  1. @CacheConfig:主要针对类配置,把@Cacheable中value=“xxx”的属性统一声明在类上,方法上不用再声明。

Alt text

  1. @CachePut: 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存。和 @Cacheable 不同的是,它每次都会触发真实方法的调用,因此经常用于更新方法,实现缓存与数据库的同步更新。
    Alt text

  2. @CacheEvict:主要针对方法配置,能够根据一定的条件对缓存进行清空。

    value--缓存的名称
    

    allEntries–是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存
    Alt text