redis 分布式缓存 springboot + redisson

926 阅读2分钟

引言

分布式缓存是降低分布式应用程序延迟、提高并发性和可伸缩性的一种重要策略。redis 是一种流行的开源内存数据存储,可用作数据库、缓存或消息代理。由于是从内存而非磁盘加载数据,redis 比许多传统的数据库解决方案更快。redisson 是一个基于 redis 的框架,用 java 实现了一个 redis 包装器(wrapper)和接口,帮助我们将 redis 集成到 springboot 上。

依赖引入

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.15.5</version>
</dependency>

2022年7月26日 github 更新 3.17.5 版本为最新。

配置 redis

在 application.yml 文件添加 redis 的配置:

spring:
  redis:
    host: "127.0.0.1" #redis的地址
    password: "123456" #默认没有密码
    database: "1" #redis默认情况下有16个分片,这里配置具体使用的分片,不配置就是0
    port: 6379 #默认端口6379
    timeout: 3000 #连接超时时间(毫秒)
    pool:
      min-idle: 20
      max-active: 30

读取配置可以使用 @Value 注解,例如读取 password:

@Value("${spring.redis.password}")
private String password;

也可以通过 @ConfigurationProperties 注解映射到配置类:

@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "spring.redisson")//获取yml文件中以spring.redisson开头的配置
public class RedissonProperties {
    private String address;
    private String password;
    private int database;
    private int timeout;
}

初始化 RedissonClient

@Configuration
public class RedissonConfig {

    @Value("redis://${spring.redis.host}:${spring.redis.port}")
    private String address;

    @Value("${spring.redis.database}")
    private Integer database;

    @Value("${spring.redis.password}")
    private String password;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${spring.redis.pool.max-active}")
    private int poolMaxActive;

    @Value("${spring.redis.pool.min-idle}")
    private int poolMinIdle;

    @Bean
    public RedissonClient redissonClient(){
        Config config = new Config();
        config.setCodec(JsonJacksonCodec.INSTANCE);
        SingleServerConfig serverConfig = config.useSingleServer();
        serverConfig.setAddress(address)
            .setDatabase(database)
            .setPassword(password)
            .setTimeout(timeout)
            .setConnectionPoolSize(poolMaxActive)
            .setConnectionMinimumIdleSize(poolMinIdle);

        return Redisson.create(config);
    }

}

创建 cache

private static class DistributedLocalCacheImpl<K, V> implements DistributedLocalCache<K, V> {

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    private final RedissonClient redissonClient;
    private final String cacheInstanceKey;
    private final DistributedLocalCacheOption cacheOption;

    private final Cache<K, Optional<V>> localCache;
    private final Function<K, V> cacheLoader;
    private final CacheEventBroadcaster cacheEventBroadcaster;

    private final KeyCodec<K> keyCodec;
    private final TypedJsonJacksonCodec valueCodec;

    public DistributedLocalCacheImpl(RedissonClient redissonClient, String cacheInstanceKey,
                                     DistributedLocalCacheOption cacheOption,
                                     CacheEventBroadcaster cacheEventBroadcaster,
                                     KeyCodec<K> keyCodec, TypeReference<V> valueTypeReference,
                                     Function<K, V> cacheLoader) {
        this.redissonClient = redissonClient;
        this.cacheInstanceKey = cacheInstanceKey;
        this.cacheOption = cacheOption.toBuilder().build();
        this.localCache = CacheBuilder.newBuilder()
            .initialCapacity(cacheOption.getInitCapacity())
            .maximumSize(cacheOption.getMaxCapacity())
            .expireAfterWrite(cacheOption.getTtl())
            .expireAfterAccess(cacheOption.getMaxIdle())
            .build();
        this.cacheEventBroadcaster = cacheEventBroadcaster;
        this.keyCodec = keyCodec;
        this.valueCodec = new TypedJsonJacksonCodec(valueTypeReference, OBJECT_MAPPER);
        this.cacheLoader = cacheLoader;
    }
@Override
public synchronized <K, V> DistributedLocalCache<K, V> createCache(String cacheInstanceKey,
                                                                   DistributedLocalCacheOption cacheOption,
                                                                   KeyCodec<K> cacheKeyCodec,
                                                                   TypeReference<V> valueTypeReference,
                                                                   Function<K, V> cacheLoader) {
    if (distributedLocalCacheMap.containsKey(cacheInstanceKey)) {
        log.error("从分布式内存二级缓存加载数据异常");
    }
    DistributedLocalCacheImpl<K, V> cache = new DistributedLocalCacheImpl<>(
        redissonClient, cacheInstanceKey, cacheOption, cacheEventBroadcaster,
        cacheKeyCodec, valueTypeReference,  cacheLoader
    );
    distributedLocalCacheMap.put(cacheInstanceKey, cache);
    return cache;
}

在其他服务类中就可以调用 createCache 方法创建缓存。

总结

综上,redisson 提供了一种集成 redis 到 springboot 并实现分布式缓存的方法,能够简便地创建内存缓存,有助于降低分布式应用程序延迟、提高并发性和可伸缩性。