技术实践第三期|HashTag在Redis集群环境下的使用

本文由友盟+技术专家分享,介绍了在数据源列表添加缓存支持时遇到的问题。由于Redis Cluster的分区策略,按照前缀查询并删除键会导致错误。为解决此问题,提出了使用HashTag生成缓存Key的方法,确保在Redis集群中正确操作。同时,文章还提及了全量数据源的缓存策略。

作者:友盟+技术专家 鹏程

一、背景

数据源列表添加缓存支持,types字段可传多值,如app, mini, web等,会构建如下缓存key,

  • application_list:123456:app
  • application_list:123456:mini
  • application_list:123456:web
  • application_list:123456:app,mini
  • application_list:123456:app,web
  • application_list:123456:mini,web
  • application_list:123456:app,mini,web
  • ...

当创建应用,更新应用或删除应用的时候,需要批量删除旧版本缓存。

二、思路

1.按照前缀 `application_list:123456`,查询所有相关的key
2.遍历keys,执行删除

/**
 * 移除缓存
 *
 * @param prefix prefix
 */
public static void deleteByPrefix(String prefix) {

    long start = System.currentTimeMillis();

    Set<String> keys;
    try {
        keys = jedisCluster.keys(CacheKeyUtils.buildCacheKey(prefix, "*"));

        LOGGER.info("cache keys {} with prefix {}", keys, prefix);
        if (keys != null && !keys.isEmpty()) {
            jedisCluster.del(keys.toArray(new String[keys.size()]));
        }
    } catch (Exception e) {
        LOGGER.error("cache deleteByPrefix error, prefix = {}", prefix, e);
        throw new BusinessException(CoreErrorEnum.CACHE_DELETE_ERROR, prefix);
    }


    long end = System.currentTimeMillis();

    LOGGER.info("cache deleteByPrefix success, prefix = {}, cost {} ms", prefix, (end - start));
}

三、问题

按照这个写完,执行报错,"JedisCluster only supports KEYS commands with patterns containing hash-tags ( curly-brackets enclosed strings )"

Redis Cluster 采用虚拟槽分区,所有的根据哈希函数映射到 0~16383 整数槽内,计算公式:slot = CRC16(key) % 16384。每个节点负责维护一部分槽以及槽所映射的键值数据,如图所示:

 

四、方案 

使用HashTag生成缓存Key

if (StringUtils.isNotEmpty(platform)) {
    cacheKey = CacheKeyUtils.buildCacheKey(
        CacheKeyUtils.buildHashTag(CacheConstant.APPLICATION_LIST, String.valueOf(userId)), "platform",
        platform);
} else if (types != null && !types.isEmpty()) {
    cacheKey = CacheKeyUtils.buildCacheKey(
        CacheKeyUtils.buildHashTag(CacheConstant.APPLICATION_LIST, String.valueOf(userId)), "types",
        types.stream().sorted().collect(Collectors.joining(",")));
} else {
    cacheKey = CacheKeyUtils.buildCacheKey(
        CacheKeyUtils.buildHashTag(CacheConstant.APPLICATION_LIST, String.valueOf(userId)));
}
  • {application_list:123456}:app
  • {application_list:123456}:mini
  • {application_list:123456}:web
  • {application_list:123456}:app,mini
  • {application_list:123456}:app,web
  • {application_list:123456}:mini,web
  • {application_list:123456}:app,mini,web
  • ...

缓存用户下全量的数据源

每次从缓存或者数据库查询当前用户下的所有数据源,按照参数筛选。

点击下面链接加入友盟+ 技术社群 
https://q-187234529230979072.a.lingyiliebian.com/code/
与超过1000+移动开发者共同讨论移动开发最新动态

欢迎点击【友盟+】,了解友盟+ 最新移动技术
欢迎关注【友盟全域数据】公众号

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值