Skip to content

Latest commit

 

History

History
192 lines (143 loc) · 6.87 KB

File metadata and controls

192 lines (143 loc) · 6.87 KB

分布式缓存设计与使用

设计说明

分布式缓存基于 redis 进行设计,在 Framework 设计中,一方面是支持缓存配置动态刷新加载;另一方面是缓存管理能力针对一些特定场景进行增强,如加密、解密可以支持国密算法、缓存磁盘、缓存监控如发现大 key(Big keys)。

分布式缓存抽象设计如下:

@startuml
package "cloudapp-base-api" {
    package "cache" {
        interface ComponentLifeCycle {
            void postStart();
            void preStop();
        }
        
        interface Interceptor<R, P> {
            R intercept(P param)
        }
        class CacheDiskInterceptor {
            void expire(byte[] key, long millis);
            void persist(byte[] key);
            void delete(byte[]... keys);
            void notifyChanged(Set<byte[]> keys);
            void notifyChanged(byte[]... keys);
        }
        abstract class DecryptInterceptor
        abstract class EncryptInterceptor
        abstract class MonitoringInterceptor {
            abstract boolean needMonitoring(byte[] value);
        }
        abstract class RefreshableRedisTemplate<K, V>
        
        Interceptor <-- EncryptInterceptor : implements
        Interceptor <-- DecryptInterceptor : implements
        Interceptor <-- MonitoringInterceptor : implements
        RedisTemplate <-- RefreshableRedisTemplate : extends
        Interceptor <-- RefreshableRedisTemplate : uses
        ComponentLifeCycle <-- RefreshableRedisTemplate : implements
    }
}

@enduml
  1. 定义缓存拦截器接口 Interceptor ,主要方法有:

    1. intercept(P param) 缓存键值对处理方法;
  2. 定义缓存磁盘拦截器接口 CacheDiskInterceptor ,主要方法由:

    1. expire(byte[] key, long millis) 设置过期时间;

    2. persist(byte[] key) 删除指定 key 的过期时间;

    3. delete(byte[]... keys) 删除 key;

    4. notifyChanged(Set<byte[]> keys) 值变更时通知;

    5. notifyChanged(byte[]... keys) 值变更时通知;     

  3. 定义加密拦截器抽象类 DecryptInterceptor ,实现接口 Interceptor ;

  4. 定义解密拦截器抽象类 EncryptInterceptor ,实现接口 Interceptor ;

  5. 定义缓存监控拦截器抽象类 MonitoringInterceptor ,实现接口 Interceptor ,只要方法有:

    1. needMonitoring(byte[] value) 是否开启监控;
  6. 定义可刷新 Redis 操作模板抽象类 RefreshableRedisTemplate ,实现接口 ComponentLifeCycle ,继承类 RedisTemplate ;

使用说明

配置说明

分布式缓存实现的配置如下:

  1. 定义分布式缓存实现的配置参数类 CloudAppRedisProperties ,使用注解 @ConfigurationProperties(CloudAppRedisProperties.PREFIX) ,其中 CloudAppRedisProperties.PREFIX = "com.alibaba.cloudapp.redis" ,继承类 RefreshableProperties ,配置参数类字段如下:
字段名 数据类型 默认值 备注
enabled boolean - 启用分布式缓存
hashMonitoring boolean false 是否监控哈希类型
valueMonitoring boolean false 是否监控 value
keyEncrypt boolean true 是否加密 key
usedHash boolean false 是否加密和解密哈希类型的 key 和 value
base org.springframework.boot.autoconfigure.data.redis.RedisProperties - -
org.springframework.boot.autoconfigure.data.redis.RedisProperties 类型的 base 字段,其主要字段如下: - - -
host String - redis 访问地址
username String - redis 访问账号
password String - redis 访问密码
port int - redis 访问端口

场景一:缓存磁盘

POM 配置

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloudapp</groupId>
            <artifactId>cloudapp-framework-dependencies</artifactId>
            <version>${cloudapp.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloudapp</groupId>
        <artifactId>spring-boot-starter-cloudapp</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloudapp</groupId>
        <artifactId>cloudapp-spring-redis</artifactId>
    </dependency>  
</dependencies>

应用配置

在环境变量中配置 redis 服务访问地址为例

spring:
  application:
    name: redis-demo

io:
  cloudapp:
    redis:
      enabled: true
      base:
        host: ${REDIS_HOST}
        port: 6379

使用验证

@Service
  public class RedisDemoService implements InitializingBean {

    @Autowired
    @Qualifier("refreshableRedisTemplate")
    private RefreshableRedisTemplateImpl redisTemplate;


    @Override
    public void afterPropertiesSet() {
        redisTemplate.opsForValue().set("testValue", "test");
        System.out.println(redisTemplate.opsForValue().get("testValue"));

        redisTemplate.opsForList().rightPushAll("testList", "test", "test2", "test3");
        System.out.println(redisTemplate.opsForList().range("testList", 0, -1));

        redisTemplate.opsForGeo().add("testGeo", new Point(1.1, 2.2), "test");
        System.out.println(redisTemplate.opsForGeo().radius("testGeo", "test", 10));

        redisTemplate.opsForHash().put("testHash", "test", "test2");
        System.out.println(redisTemplate.opsForHash().get("testHash", "test"));

        redisTemplate.opsForSet().add("testSet", "test", "test2");
        System.out.println(redisTemplate.opsForSet().members("testSet"));

        redisTemplate.opsForHyperLogLog().add("testLog", Collections.singletonMap("test", "test2"));
        System.out.println(redisTemplate.opsForHyperLogLog().size("testLog"));

        RecordId id = redisTemplate.opsForStream().add("testStream", Collections.singletonMap("test", "test2"));

        redisTemplate.opsForValue().getAndDelete("testValue");
        redisTemplate.opsForList().leftPop("testList", 3);
        redisTemplate.opsForGeo().remove("testGeo", "test");
        redisTemplate.opsForHash().delete("testHash", "test");
        redisTemplate.opsForSet().remove("testSet", "test", "test2");
        redisTemplate.opsForHyperLogLog().delete("testLog");
        redisTemplate.opsForStream().delete("testStream", id);

    }
}