架构之旅-集群与管理-数据-Redis

简述

本文中,将改进数据服务。使用redis集群来提供缓存服务。

源代码

iarc-data

环境

IDE: IntelliJ IDEA
JDK: 1.8.0_u162
Framework: spring boot, dubbo
Cache: Redis
WebServer: Tomcat (本地端口8088)

开发

pom dependency

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

appliation.properties redis配置

通用

1
2
3
4
5
6
spring.redis.database=2
spring.redis.timeout=10000
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=1
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1

单实例

1
2
3
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=****

Sentinel集群

1
2
spring.redis.sentinel.master=mymaster
spring.redis.sentinel.nodes=192.168.56.103:29000,192.168.56.103:29001,192.168.56.103:29002

配置类

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package cn.icmyfuture.iarc.data.common;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class RedisCacheConfig extends CachingConfigurerSupport {
private static final Map<String, Long> cacheMap = new HashMap<String, Long>();

public static void setCacheTime(String key, Long cacheTime){
cacheMap.put(key, cacheTime);
}

@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append("v2:");
sb.append(target.getClass().getName()+":");
sb.append(method.getName()+":");
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}

@SuppressWarnings("rawtypes")
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setExpires(cacheMap);
return cacheManager;
}

@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}

CacheConfig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package cn.icmyfuture.iarc.data.config;

import cn.icmyfuture.iarc.data.common.RedisCacheConfig;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableCaching
public class CacheConfig extends RedisCacheConfig {
public static final String getAllUsers = "getAllUsers";

static {
setCacheTime(getAllUsers, 180L);
}
}

SpringBoot开启缓存

1
2
@EnableCaching
public class DataApplication extends SpringBootServletInitializer

Service实现中,使用redis缓存

由于dubbo不支持使用注解@Cacheable,只能选择以下2种解决方式之一(本文使用第一种方式,对key的设置有更大的灵活性)

  • 使用@Service注解,在代码中获取/设置缓存
  • 不使用@Service注解,使用dubbo配置的方式来注册服务,同时开启缓存
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    @Service
    public class UserServiceImpl implements UserService {
    @Autowired
    UserDao userDao;

    @Autowired
    private CacheManager cacheManager;

    @Override
    public List<User> getAllUsers() {
    Cache cache = cacheManager.getCache(CacheConfig.getAllUsers);
    String key = String.format("%s", CacheConfig.getAllUsers);
    Cache.ValueWrapper wrapper = cache.get(key);
    List<User> users;
    if (wrapper == null) {
    users = userDao.getAllUsers();
    cache.put(key, users);
    return users;
    }
    return (List<User>) wrapper.get();
    }

调试

  • 访问http://localhost:8002/user/getAllUsers来验证redis缓存的有效性
  • 访问http://localhost:8002/druid/index.html来查看SQL监控以验证sql仅被执行了一次

部署

centos下配置好redis。maven工程根目录下执行命令mvn clean install,然后将iarc-data与iarc-service部署到tomcat中,访问http://localhost:8080/service/user/getAllUsers

参考