名词解释

  • BaseCacheExecutor:Lcache中连接资源的实例,对所有命令的封装集成;后面简称 CacheExecutor
  • cacheType:Lcache中每个CacheExecutor的唯一标识;一个服务可以有多个CacheExecutor,每个CacheExecutor可配置不同的连接方式,监控统计也会不同;

    一、创建CacheExecutor

    1. BaseCacheExecutor cacheExecutor = CacheClientFactory.builder()
    2. .cacheType("cacheType")
    3. .connectType(ConnectTypeEnum.SIMPLE)
    4. .clientType(RedisClientConstants.LETTUCE)
    5. .configSourceType(CacheConfigSourceTypeEnum.CUSTOM)
    6. .cacheConfig(new LettuceConnectSourceConfig("127.0.0.1", 6379, "", 2000))
    7. .addLua(Arrays.asList(() -> "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end"))
    8. .isLocalCache(false)
    9. .localCacheKeys("key1", "key2")
    10. .monitorHotKeyMinValue(5000)
    11. .isOpenMonitor(true)
    12. .monitorHotKeyInterval(5000L)
    13. .monitorHotKeyLeastValue(10)
    14. .monitorHotKeyStatisticCapacity(50)
    15. .build();

    配置介绍

  • cacheType:CacheExecutor的唯一标识,不能为空;

  • connectType连接客户端类型,默认Lettuce客户端连接,可不传
  • clientType连接方式,默认Lettuce单连接
  • configSourceType
    配置客户端Redis连接数据源配置
    默认DB方式,需重写资源配置DbCacheConfigManager中的getConfig方法
    同理,Apollo配置重写ApolloCacheConfigManager
    当然也可以自己实现AbstractConfigManager并注册到资源管理工厂CacheConfigFactory
  • cacheConfig:如果选用服务直连方式,则采用此方式
  • addLua:增加lua脚本,通过executor.executeByLua使用
  • isLocalCache:是否本地缓存,默认关闭,待线上测试支持,目前支持STRING/HASH/SET3种数据类型
  • localCacheKeys:使用前需开启本地缓存,开启后对指定key进行本地缓存,支持分布式,目前支持STRING/HASH/SET3种数据类型
  • monitorHotKeyMinValue:设置热key单POD进行多级缓存操作的起始值,默认5000,请根据POD数量与redis配置设置
  • isOpenMonitor:是否开启监控,默认开启
  • monitorHotKeyInterval热key同步频率,默认5s
  • monitorHotKeyLeastValue热key收集频率内的起始值,默认 10
  • monitorHotKeyStatisticCapacity热key容量,默认收集TOP前50

    SimpleDemo

    ```java //非Spring方式 BaseCacheExecutor baseCacheExecutor = CacheClientFactory.getCacheExecutor(“test”, new LettuceConnectSourceConfig());

//Spring方式,注入BaseCacheExecutor,需要实现DB资源配置,或修改LcacheBeanProcessor中CacheExecutor的实例化方式 @Lcache(cacheType = “test”) private BaseCacheExecutor cacheExecutor;

<a name="WWwm8"></a>
### 配置DB数据源
```java
/**
* @Title: DbCacheConfigManagerImpl
* @Description: 重写默认DB连接资源,连接本地
* @author JerryLong
* @date 2022/1/13 3:02 PM
* @version V1.0
*/
@Component
public class DbCacheConfigManagerImpl extends DbCacheConfigManager {

    @Override
    protected BaseCacheConfig getConfig(CacheConfigModel cacheConfigModel) {
        /**
         * TODO 调用DB查询接口
         * TODO 并根据连接客户端类型 cacheConfigModel.getClientType() 与 连接方式 cacheConfigModel.getConnectTypeEnum() 创建不同的连接配置
         */
        return new LettuceConnectSourceConfig();
    }
}

BaseCacheConfig接口实现

  • JedisConnectSourceConfig
  • JedisClusterConnectSourceConfig
  • JedisShardConnectSourceConfig
  • LettuceConnectSourceConfig
  • LettuceClusterConnectSourceConfig

    �二、使用

    1、普通命令

    baseCacheExecutor.set("test","test",60);
    String test = baseCacheExecutor.get("test");
    baseCacheExecutor.hset("htest","key1","val1",60);
    String hget = baseCacheExecutor.hget("htest", "key1");
    

    2、阻塞式命令

    while (true){
      try {
          //超时时间不能大于CacheExecutor连接配置中的超时时间
          List<String> data = baseCacheExecutor.brpop(1, "list");
      } catch (Exception e) {
          e.printStackTrace();
      }
    }
    

    3、发布订阅

    //发布
    baseCacheExecutor.publish("test", "msg");
    //订阅
    baseCacheExecutor.subscribe((message) -> {
      System.out.println("Lettuce Local订阅消息:" + message);
    }, "test");
    

    4、通过Lua脚本执行

    ```java //实现RedisLuaInterface接口 private static enum TestLua implements RedisLuaInterface { TEST_UN_LOCK(“if redis.call(‘get’,KEYS[1]) == ARGV[1] then return redis.call(‘del’,KEYS[1]) else return 0 end”), ; private String scripts;

    TestLua(String scripts) {

      this.scripts = scripts;
    

    }

    @Override public String getScripts() {

      return scripts;
    

    } }

//注入Lua脚本 List luas = new ArrayList<>(); luas.add(TestLua.TEST_UN_LOCK); baseCacheExecutor.addLua(luas);

//调用 lettuce.executeByLua(TestLua.TEST_UN_LOCK, Arrays.asList(“test”), Arrays.asList(“test”));

<a name="OP2pE"></a>
#### 5、分布式锁
```java
//阻塞式lock,支持tryLock
RLock lock = baseCacheExecutor.lock("lock", 10, TimeUnit.SECONDS);
try {
    if (null != lock) {
        System.out.println(i + "加锁成功");
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    //需要使用封装的unlock方法,Rlock本身不判断锁是否当前线程持有
    baseCacheExecutor.unLock(lock);
    System.out.println(i + "解锁成功");
}

异常处理

对外统一抛出 CacheException