项目场景:

提示:这里简述项目相关背景:

例如:项目场景:查平台的支付方式


问题描述

用来redis的scan模糊匹配的方式,查询key,在redis的key大于百万级的key的时候,会导致查询非常缓慢

package com.hznt.yeahgo.cms.portal.utils;import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;/*** @author wangwenping* @description redis helper* @date 2021/5/14*/
@Slf4j
public class RedisHelper {/*** scan 实现** @param redisTemplate* @param pattern       表达式* @param consumer      对迭代到的key进行操作*/public static void scan(RedisTemplate redisTemplate, String pattern, Consumer<byte[]> consumer) {//pattern="*"+pattern+"*";//String finalPattern = pattern;redisTemplate.execute((RedisConnection connection) -> {try (Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().count(1000000).match(pattern).build())) {cursor.forEachRemaining(consumer);return null;} catch (IOException e) {log.error("redis scan 发生异常 {}", e);throw new RuntimeException(e);}});}/*** 获取符合条件的key** @param pattern 表达式* @return*/public static List<String> keys(RedisTemplate redisTemplate, String pattern) {List<String> keys = new ArrayList<>();scan(redisTemplate, pattern, item -> {//符合条件的keyString key = new String(item, StandardCharsets.UTF_8);keys.add(key);});return keys;}
}``   String resourceKey = cmsResourceByResourceKeyRequest.getResourceKey();String patternAll = CacheKey.getResourceKey(resourceKey, "*" + cmsResourceByResourceKeyRequest.getPlatform() + "*", "0.0.0");List<String> keys = RedisHelper.keys(redisTemplate, patternAll);# 原因分析:
方法1:使用KEYS [pattern]:查找所有符合给定模式pattern的key使用keys [pattern]指令可以找到所有符合pattern条件的key,但是keys会一次性返回所有符合条件的key,所以会造成redis的卡顿,假设redis此时正在生产环境下,使用该命令就会造成隐患,另外如果一次性返回所有key,对内存的消耗在某些条件下也是巨大的。例:keys test* //返回所有以test为前缀的key
方法2:使用SCAN cursor [MATCH pattern] [COUNT count]cursor:游标
MATCH pattern:查询key的条件
count:返回的条数
SCAN是一个基于游标的迭代器,需要基于上一次的游标延续之前的迭代过程。SCAN以0作为游标,开始一次新的迭代,直到命令返回游标0完成一次遍历。此命令并不保证每次执行都返回某个给定数量的元素,甚至会返回0个元素,但只要游标不是0,程序都不会认为SCAN命令结束,但是返回的元素数量大概率符合count参数。另外,SCAN支持模糊查询。例:SCAN 0 MATCH test* COUNT 10 //每次返回10条以test为前缀的key
用游标和模糊匹配找key的方式,在key非常多的时候,内存消耗也会很严重,导致查询慢---# 解决方案:
>把这些相关的key,用String的方式或者hash或者listd的形式存储,用java代码来去查找匹配/*** 平台放最后* @param key* @return*/public static  String getLastKeys(String  key,String appVersion,String platform){String resourceKey = new StringBuilder(ResourceConstant.toClientSourceKey).append(":").append(key).append(":").append("appVersion").append(":").append(appVersion).append(":").append("platform").append(":").append(platform).toString();return resourceKey;}//获取版本号和平台对应的key    iOS&Android&MiniProgram&H5&FlutterAndroid&FultterIos    2.0.0的形式
  String ishasKey = CacheKey.getLastKeys(resourceKey, appVersion, platform);log.info("要去截取的key"+ishasKey);String lastPlatform = ishasKey.substring(ishasKey.lastIndexOf(":") + 1);log.info("截取的后面的{}",lastPlatform);//截取前面的String beforePlateform = ishasKey.substring(0, ishasKey.lastIndexOf(":"));log.info("截取的前面的{}",beforePlateform);List<String> resourceResponseList = JSON.parseArray(cmsData, String.class);//拿出全部的keyif (!CollectionUtils.isEmpty(resourceResponseList)) {log.info("redis资源位key的数量为{}",resourceResponseList.size());for (String key : resourceResponseList) {//将平台切割出来String lastPlatform1 = key.substring(key.lastIndexOf(":") + 1);//截取前面的String beforePlateform1 = key.substring(0, key.lastIndexOf(":"));if (beforePlateform1.equals(beforePlateform) && lastPlatform1.contains(lastPlatform)) {finalKey = beforePlateform1 +":"+ lastPlatform1;break;}}log.info("要查的最终匹配的key{}",finalKey);}return finalKey;

redis的游标和模糊查询key的不适用相关推荐

  1. redis通过key模糊搜索_jedis模糊查询key

    jedis模糊查询key 2018-11-26 redis里面存的key是byte[]类型,怎么使用jedis进行key的模糊查询 在redis里面存储了一些数据,key和value都是byte[]类 ...

  2. StackExchange.Redis 使用LuaScript脚本模糊查询hash

    获取redis连接 public class RedisHelper{private static readonly string ConnectionString = ConfigurationMa ...

  3. Redis模糊查询及批量删除key

    Redis模糊查询及标题批量删除key 一.登录redis,常用操作 登录本机redis服务器:redis-cli 输入密码验证:auth password 查看所有key:keys * 设置key: ...

  4. Redis实现分页和多条件模糊查询方案

    导言 Redis是一个高效的内存数据库,它支持包括String.List.Set.SortedSet和Hash等数据类型的存储,在Redis中通常根据数据的key查询其value值,Redis没有模糊 ...

  5. php redis批量删除key,redis批量删除某种规则的key

    一.前言 在工作中经常遇到需要批量删除某种规则的key的情况,如缓存的课程数据"course-课程uid",课程uid是变量,我们需要删除类似于"course-*&quo ...

  6. key redis 模糊查询个数_Reids Lua 模糊查询所有key 及 相对应的集合总数

    Redis 使用 Lua 模糊查询所有key 及 相对应的集合总数 .Net 4.5.1 需要引入:    StackExchange.Redis  (测试用的 1.2.4.0) 方法一: 优点:原子 ...

  7. Redis命令:scan实现模糊查询

    1.scan前言 从Redis v2.8开始,SCAN命令已经可用,它允许使用游标从keyspace中检索键. 对比KEYS命令,虽然SCAN无法一次性返回所有匹配结果,但是却规避了阻塞系统这个高风险 ...

  8. Redis批量操作--增加,删除,模糊查询

    需求来源 虽然说redis是纯内存操作,效率非常高,但是一次插入或者删除千万级或者亿级的操作,如果采用单条处理的api,整体处理效率还是很低的:另外,如果处理的数据量过大,稍有不慎可能就会导致clie ...

  9. Reids Lua 模糊查询所有key 及 相对应的集合总数

    Redis 使用 Lua 模糊查询所有key 及 相对应的集合总数 .Net 4.5.1 需要引入:    StackExchange.Redis  (测试用的 1.2.4.0) 方法一: 优点:原子 ...

最新文章

  1. 用 Flask 来写个轻博客 (5) — (M)VC_SQLAlchemy 的 CRUD 详解
  2. 分布式系统中一致性哈希算法
  3. 家用电器用户行为分析与事件识别_8个步骤,教你如何开始用户行为分析
  4. CRM lifecycle status
  5. .net core通过多路复用实现单服务百万级别RPS吞吐
  6. 华人学者黄皓两页证明解决计算机科学领域难题:布尔函数敏感度猜想
  7. windows永久添加路由
  8. 201521123063 《Java程序设计》 第7周学习总结
  9. 服务器可用性监测系统,可用性监控区别
  10. ueditor样式过滤问题
  11. 实用防火墙(Iptables)脚本分析
  12. JSP(二):JSP页面组成部分
  13. Git合并特定commits 到另一个分支
  14. 《云计算核心技术剖析》学习笔记
  15. Linux设置每分钟、每小时、每天、每周、每月、每年定时执行
  16. 解决Microsoft Edge与Chrome地址栏使用必应搜索bing.com很慢的问题
  17. jasperReport:Eclipse-Ireport插件安装及基本使用
  18. 分享一个很好的卸载绿色软件:Geek Uninstaller(个人用户免费)
  19. 配置photon服务器,unity连接Photon
  20. (18)ROS学习-TF坐标变换之静态坐标变换

热门文章

  1. JavaIO流,万物皆文件
  2. IT行业都有哪些岗位?
  3. matplotlib+basemap画出标记地图
  4. 免费的可直接运行的简单易懂的C++学生信息管理系统
  5. C语言入门习题系列三(含答案)
  6. python代码画樱花-如何用Python代码实现樱花树效果
  7. 算例在线帮 | 某型无厚度翅片水冷板散热的Fluent仿真分析
  8. 胶质瘤新发现丨神经胶质瘤标志物研究
  9. 阿里,淘宝,天猫,京东2012年的大概销售额
  10. 壳 查壳 去壳 加壳的基本原理