Redis 中 keys 命令带来的线上性能问题,怎么解决?
mhr18 2024-11-20 18:43 23 浏览 0 评论
推荐学习
- 2020春招必备:MySQL(20)与Redis(20),不看答案能答对几道?
- 牛掰!“基础-中级-高级”Java程序员面试集结,看完献出我的膝盖
- 这是什么神仙面试宝典?半月看完25大专题,居然斩获阿里P7offer
起因
下午接到运维反馈,生产redis有个执行keys的命令请求太慢了,要两三秒才能响应
涉及命令如下:
KEYS ttl_600::findHeadFootData-15349232-*-head
什么是keys命令?
keys官方文档 http://www.redis.cn/commands/keys.html
KEYS pattern
查找所有符合给定模式pattern(正则表达式)的 key 。
时间复杂度为O(N),N为数据库里面key的数量。
例如,Redis在一个有1百万个key的数据库里面执行一次查询需要的时间是40毫秒 。
警告: KEYS 的速度非常快,但在一个大的数据库中使用它仍然可能造成性能问题,如果你需要从一个数据集中查找特定的 KEYS, 你最好还是用 Redis 的集合结构 SETS 来代替。
支持的正则表达模式:
h?llo 匹配 hello, hallo 和 hxllo
h*llo 匹配 hllo 和 heeeello
h[ae]llo 匹配 hello 和 hallo, 但是不匹配 hillo
h[^e]llo 匹配 hallo, hbllo, … 但是不匹配 hello
h[a-b]llo 匹配 hallo 和 hbllo
返回值
所有符合条件的key
Redis提供的所有API操作,相对于服务端方面都是one by one执行的,命令是一个接着一个执行的,不存在并行执行的情况。
虽说REDIS执行KEYS命令很快,但是由于生产环境上有近六百万KEY,以至于KEYS命令需要两三秒,这两三秒就会导致其它命令阻塞着,这在生产中是灾难性的;
redis提供了一个scan的命令
scan命令官方文档 http://www.redis.cn/commands/scan.html
SCAN cursor [MATCH pattern] [COUNT count]
cursor 游标
[MATCH pattern] 需要正则匹配的字符串
count 扫描的key的个数
SCAN 命令及其相关的 SSCAN, HSCAN 和 ZSCAN 命令都用于增量迭代一个集合元素。
- SCAN 命令用于迭代当前数据库中的key集合。
- SSCAN 命令用于迭代SET集合中的元素。
- HSCAN 命令用于迭代Hash类型中的键值对。
- ZSCAN 命令用于迭代SortSet集合中的元素和元素对应的分值
栗子
redis 127.0.0.1:6379> scan 0 MATCH *11*
1) "288"
2) 1) "key:911"
redis 127.0.0.1:6379> scan 288 MATCH *11*
1) "224"
2) (empty list or set)
redis 127.0.0.1:6379> scan 224 MATCH *11*
1) "80"
2) (empty list or set)
redis 127.0.0.1:6379> scan 80 MATCH *11*
1) "176"
2) (empty list or set)
redis 127.0.0.1:6379> scan 176 MATCH *11* COUNT 1000
1) "0"
2) 1) "key:611"
2) "key:711"
3) "key:118"
4) "key:117"
5) "key:311"
6) "key:112"
7) "key:111"
8) "key:110"
9) "key:113"
10) "key:211"
11) "key:411"
12) "key:115"
13) "key:116"
14) "key:114"
15) "key:119"
16) "key:811"
17) "key:511"
18) "key:11"
redis 127.0.0.1:6379>
在上面这个例子中, 第一次迭代使用 0 作为游标, 表示开始一次新的迭代。第二次迭代使用的是第一次迭代时返回的游标 17 ,作为新的迭代参数 。
显而易见,SCAN命令的返回值 是一个包含两个元素的数组, 第一个数组元素是用于进行下一次迭代的新游标, 而第二个数组元素则是一个数组, 这个数组中包含了所有被迭代的元素。
在第二次调用 SCAN 命令时, 命令返回了游标 0 , 这表示迭代已经结束, 整个数据集已经被完整遍历过了。
以 0 作为游标开始一次新的迭代, 一直调用 SCAN 命令, 直到命令返回游标 0 , 我们称这个过程为一次完整遍历。
java代码实践一下
上面已经说了keys和scan的命令了,下面用jedis来进行实践一下,在本地编码自测:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.3</version>
</dependency>
<!--hutool工具类的jar包不是必须的,我是用习惯这个工具类了,你们有其他工具类直接去掉hutool即可-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.6.5</version>
</dependency>
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.thread.ExecutorBuilder;
import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.ScanParams;
import redis.clients.jedis.ScanResult;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
public class JedisService {
public static Jedis getJedis(){
return new Jedis("localhost",6379,1000000000);
}
volatile static Boolean testCycleSetExitFlag = Boolean.FALSE;
/**
* 初始化数据到redis
*/
public static void initData() throws InterruptedException {
TimeInterval timeInterval = DateUtil.timer();
log.info("initData start");
getJedis().set("111CCCCCCCCCCCCCC1111","1");//先把查找的key设置进去
//初始化数据个数
AtomicInteger count = new AtomicInteger(10000*2000);
//开100个客户端去执行set命令
Integer totalClientNum = 100;
ExecutorService executor = ExecutorBuilder.create()
.setCorePoolSize(10)
.setMaxPoolSize(50)
.setWorkQueue(new LinkedBlockingQueue<>(1024))
.build();
CountDownLatch countDownLatch = new CountDownLatch(totalClientNum);
for (int i = 0; i < totalClientNum; i++) {
executor.submit(()->{
Jedis jedis = getJedis();
while (true){
Integer crrentCount = count.decrementAndGet();
if(crrentCount<=0){
break;
}
if(crrentCount%10000==0){
log.info(" 设置key的数量还剩:{} 已耗时:{}毫秒",crrentCount,timeInterval.interval());
}
jedis.set(UUID.randomUUID().toString().replaceAll("-",""),"1");
}
countDownLatch.countDown();
});
}
countDownLatch.await();
log.info("initData end 总耗时:{}毫秒",timeInterval.interval());
executor.shutdown();
}
public static void main(String[] args) throws Exception {
Jedis jedis = getJedis();
System.out.println("服务正在运行: "+jedis.ping());
// initData();//初始化数据
log.info("现在redis服务有{}个key",jedis.dbSize());
String pattern = "*CCCCCCCCCCCCCC*";
//第一步:先验证一下keys和scan的执行效率
keys(pattern);
scan(pattern);
log.info("----------------我是一条分割线---------------");
//第二步:来验证一下keys和scan命令是否会阻塞其它命令
new Thread(()->{
testCycleSet("1111","11");
}).start();
Thread.sleep(2000);//休眠两秒
keys(pattern);
scan(pattern);
testCycleSetExitFlag = true;
log.info("----------------我还是一条分割线---------------");
//下面测试一下设置不同count的效率
scan(pattern,100);
scan(pattern,200);
scan(pattern,300);
scan(pattern,400);
scan(pattern,500);
scan(pattern,1000);
scan(pattern,2000);
scan(pattern,5000);
scan(pattern,10000);
}
//循环设置一个key值 测试用的
public static void testCycleSet(String key,String value){
Jedis jedis = getJedis();
while (true){
if(testCycleSetExitFlag){
break;
}
Long startTime = System.currentTimeMillis();
log.info("testCycleSet key:{} value:{} start",key,value);
try {
jedis.set(key,value);
}catch (Exception e){
log.error("testCycleSet",e);
}
log.info("testCycleSet key:{} value:{} end 耗时:{}毫秒",key,value,(System.currentTimeMillis() - startTime));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static Set<String> keys(String pattern){
Long startTime = System.currentTimeMillis();
log.info("jedis keys start 匹配的key:{}",pattern);
Set<String> keySet = getJedis().keys(pattern);
log.info("jedis keys end 匹配的key:{} 结果集大小:{} 耗时:{}毫秒 ",pattern,keySet.size(),(System.currentTimeMillis() - startTime));
return keySet;
}
public static Set<String> scan(String pattern){
return scan(pattern,300);
}
public static Set<String> scan(String pattern,int count){
Long startTime = System.currentTimeMillis();
Jedis jedis = getJedis();
log.info("jedis scan start 匹配的key:{} 每次遍历{}个key",pattern,count);
String index = "0";
Set<String> keySet = new HashSet<String>();//匹配到的结果集
Integer scanNum = 0;
try {
ScanParams params = new ScanParams();
params.match(pattern);
params.count(count);
while (true){
ScanResult<String> scanResult = jedis.scan(index,params);
index = scanResult.getStringCursor();//下标重新赋值
List<String> result = scanResult.getResult();//扫描到的key值
if(CollUtil.isNotEmpty(result)){
keySet.addAll(result);//扫描到的key放到Set
}
if("0".equals(index)){
break;
}
scanNum++;
}
} catch (Exception e) {
log.info("redis异常" + e.getMessage());
}
log.info("jedis scan end 匹配的key:{} 每次遍历{}个key scan执行了:{}次 结果集大小:{} 总耗时:{}毫秒",pattern,count,scanNum,keySet.size(),(System.currentTimeMillis() - startTime));
return keySet;
}
}
服务正在运行: PONG
00:34:30.776 [main] INFO com.test.JedisService - 现在redis服务有25000000个key
00:34:30.780 [main] INFO com.test.JedisService - jedis keys start 匹配的key:*CCCCCCCCCCCCCC*
00:34:41.493 [main] INFO com.test.JedisService - jedis keys end 匹配的key:*CCCCCCCCCCCCCC* 结果集大小:1 耗时:10713毫秒
00:34:41.493 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历300个key
00:35:09.307 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历300个key scan执行了:83231次 结果集大小:1 总耗时:27814毫秒
00:35:09.307 [main] INFO com.test.JedisService - ----------------我是一条分割线---------------
00:35:09.352 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:09.355 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:3毫秒
00:35:10.358 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:10.359 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:11.356 [main] INFO com.test.JedisService - jedis keys start 匹配的key:*CCCCCCCCCCCCCC*
00:35:11.360 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:22.724 [main] INFO com.test.JedisService - jedis keys end 匹配的key:*CCCCCCCCCCCCCC* 结果集大小:1 耗时:11368毫秒
00:35:22.725 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:11365毫秒
00:35:22.725 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历300个key
00:35:23.728 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:23.729 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:1毫秒
00:35:24.734 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:24.735 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:1毫秒
00:35:25.739 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:25.740 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:1毫秒
00:35:26.744 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:26.744 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:27.747 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:27.747 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:28.751 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:28.751 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:29.755 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:29.757 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:1毫秒
00:35:30.761 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:30.761 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:31.766 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:31.767 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:1毫秒
00:35:32.767 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:32.768 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:1毫秒
00:35:33.772 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:33.773 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:1毫秒
00:35:34.776 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:34.776 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:35.779 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:35.780 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:1毫秒
00:35:36.784 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:36.785 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:1毫秒
00:35:37.788 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:37.788 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:38.793 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:38.793 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:39.796 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:39.796 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:40.797 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:40.797 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:41.800 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:41.801 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:1毫秒
00:35:42.806 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:42.806 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:43.811 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:43.811 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:44.816 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:44.816 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:45.821 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:45.821 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:46.826 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:46.826 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:47.830 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:47.830 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:48.835 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:48.835 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:49.840 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:49.840 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:50.845 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 start
00:35:50.845 [Thread-0] INFO com.test.JedisService - testCycleSet key:1111 value:11 end 耗时:0毫秒
00:35:51.225 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历300个key scan执行了:83231次 结果集大小:1 总耗时:28500毫秒
00:35:51.225 [main] INFO com.test.JedisService - ----------------我还是一条分割线---------------
00:35:51.226 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历100个key
00:36:24.747 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历100个key scan执行了:249070次 结果集大小:1 总耗时:33522毫秒
00:36:24.747 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历200个key
00:36:54.580 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历200个key scan执行了:124768次 结果集大小:1 总耗时:29833毫秒
00:36:54.580 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历300个key
00:37:23.674 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历300个key scan执行了:83231次 结果集大小:1 总耗时:29094毫秒
00:37:23.674 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历400个key
00:37:56.541 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历400个key scan执行了:62441次 结果集大小:1 总耗时:32867毫秒
00:37:56.542 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历500个key
00:38:28.282 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历500个key scan执行了:49962次 结果集大小:1 总耗时:31740毫秒
00:38:28.282 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历1000个key
00:39:00.211 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历1000个key scan执行了:24990次 结果集大小:1 总耗时:31929毫秒
00:39:00.211 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历2000个key
00:39:31.754 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历2000个key scan执行了:12497次 结果集大小:1 总耗时:31543毫秒
00:39:31.754 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历5000个key
00:40:03.548 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历5000个key scan执行了:4999次 结果集大小:1 总耗时:31794毫秒
00:40:03.548 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历10000个key
00:40:36.329 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历10000个key scan执行了:2499次 结果集大小:1 总耗时:32781毫秒
这是500万key 不同count执行的结果
服务正在运行: PONG
01:23:29.449 [main] INFO com.test.JedisService - 现在redis服务有5000000个key
01:23:29.452 [main] INFO com.test.JedisService - jedis keys start 匹配的key:*CCCCCCCCCCCCCC*
01:23:31.172 [main] INFO com.test.JedisService - jedis keys end 匹配的key:*CCCCCCCCCCCCCC* 结果集大小:1 耗时:1720毫秒
01:23:31.172 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历300个key
01:23:36.587 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历300个key scan执行了:16649次 结果集大小:1 总耗时:5415毫秒
01:23:36.587 [main] INFO com.test.JedisService - ----------------我还是一条分割线---------------
01:23:36.587 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历100个key
01:23:43.030 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历100个key scan执行了:49851次 结果集大小:1 总耗时:6443毫秒
01:23:43.031 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历200个key
01:23:48.801 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历200个key scan执行了:24963次 结果集大小:1 总耗时:5769毫秒
01:23:48.801 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历300个key
01:23:54.355 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历300个key scan执行了:16649次 结果集大小:1 总耗时:5554毫秒
01:23:54.355 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历400个key
01:23:59.711 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历400个key scan执行了:12490次 结果集大小:1 总耗时:5356毫秒
01:23:59.711 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历500个key
01:24:05.016 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历500个key scan执行了:9994次 结果集大小:1 总耗时:5305毫秒
01:24:05.016 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历1000个key
01:24:11.594 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历1000个key scan执行了:4998次 结果集大小:1 总耗时:6578毫秒
01:24:11.594 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历2000个key
01:24:18.137 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历2000个key scan执行了:2499次 结果集大小:1 总耗时:6543毫秒
01:24:18.137 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历5000个key
01:24:24.655 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历5000个key scan执行了:999次 结果集大小:1 总耗时:6518毫秒
01:24:24.655 [main] INFO com.test.JedisService - jedis scan start 匹配的key:*CCCCCCCCCCCCCC* 每次遍历10000个key
01:24:31.257 [main] INFO com.test.JedisService - jedis scan end 匹配的key:*CCCCCCCCCCCCCC* 每次遍历10000个key scan执行了:499次 结果集大小:1 总耗时:6602毫秒
小结
keys和scan是否会阻塞其他命令?
看日志显而易见
keys命令会阻塞其它命令
scan命令则相当于分批次遍历全部key,遍历一部分key后把,所在位置(游标)返回给客户端,下次客户端拿着上次返回的游标,继续执行scan命令往后遍历,直至遍历完成,所以不会长时间阻塞redis。
scan命令count设置多大合适
我们redis服务器上面key的数量通常在五百万到七百万这个范围
经过上面测试:
scan命令 count设置成300
两千五百万的key会执行八万次的scan,耗时30秒就能遍历完,每秒大概执行3000次
五百万的key 会执行16649次的scan,总耗时6秒,每秒大概执行3000次
而生产上redis的的qps很轻松地扛住10w,所以设置300会比较合适。
最终
本地自测通过,发到灰度环境,测试反馈业务无异常,发到生产观察了几天运维也没不良的反馈,问题解决~
原文链接:https://www.cnblogs.com/x-kq/p/14782035.html
相关推荐
- 【推荐】一个开源免费、AI 驱动的智能数据管理系统,支持多数据库
-
如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!.前言在当今数据驱动的时代,高效、智能地管理数据已成为企业和个人不可或缺的能力。为了满足这一需求,我们推出了这款开...
- Pure Storage推出统一数据管理云平台及新闪存阵列
-
PureStorage公司今日推出企业数据云(EnterpriseDataCloud),称其为组织在混合环境中存储、管理和使用数据方式的全面架构升级。该公司表示,EDC使组织能够在本地、云端和混...
- 对Java学习的10条建议(对java课程的建议)
-
不少Java的初学者一开始都是信心满满准备迎接挑战,但是经过一段时间的学习之后,多少都会碰到各种挫败,以下北风网就总结一些对于初学者非常有用的建议,希望能够给他们解决现实中的问题。Java编程的准备:...
- SQLShift 重大更新:Oracle→PostgreSQL 存储过程转换功能上线!
-
官网:https://sqlshift.cn/6月,SQLShift迎来重大版本更新!作为国内首个支持Oracle->OceanBase存储过程智能转换的工具,SQLShift在过去一...
- JDK21有没有什么稳定、简单又强势的特性?
-
佳未阿里云开发者2025年03月05日08:30浙江阿里妹导读这篇文章主要介绍了Java虚拟线程的发展及其在AJDK中的实现和优化。阅前声明:本文介绍的内容基于AJDK21.0.5[1]以及以上...
- 「松勤软件测试」网站总出现404 bug?总结8个原因,不信解决不了
-
在进行网站测试的时候,有没有碰到过网站崩溃,打不开,出现404错误等各种现象,如果你碰到了,那么恭喜你,你的网站出问题了,是什么原因导致网站出问题呢,根据松勤软件测试的总结如下:01数据库中的表空间不...
- Java面试题及答案最全总结(2025版)
-
大家好,我是Java面试陪考员最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Spring、MySQL、JVM、Redis、Linux、Sprin...
- 数据库日常运维工作内容(数据库日常运维 工作内容)
-
#数据库日常运维工作包括哪些内容?#数据库日常运维工作是一个涵盖多个层面的综合性任务,以下是详细的分类和内容说明:一、数据库运维核心工作监控与告警性能监控:实时监控CPU、内存、I/O、连接数、锁等待...
- 分布式之系统底层原理(上)(底层分布式技术)
-
作者:allanpan,腾讯IEG高级后台工程师导言分布式事务是分布式系统必不可少的组成部分,基本上只要实现一个分布式系统就逃不开对分布式事务的支持。本文从分布式事务这个概念切入,尝试对分布式事务...
- oracle 死锁了怎么办?kill 进程 直接上干货
-
1、查看死锁是否存在selectusername,lockwait,status,machine,programfromv$sessionwheresidin(selectsession...
- SpringBoot 各种分页查询方式详解(全网最全)
-
一、分页查询基础概念与原理1.1什么是分页查询分页查询是指将大量数据分割成多个小块(页)进行展示的技术,它是现代Web应用中必不可少的功能。想象一下你去图书馆找书,如果所有书都堆在一张桌子上,你很难...
- 《战场兄弟》全事件攻略 一般事件合同事件红装及隐藏职业攻略
-
《战场兄弟》全事件攻略,一般事件合同事件红装及隐藏职业攻略。《战场兄弟》事件奖励,事件条件。《战场兄弟》是OverhypeStudios制作发行的一款由xcom和桌游为灵感来源,以中世纪、低魔奇幻为...
- LoadRunner(loadrunner录制不到脚本)
-
一、核心组件与工作流程LoadRunner性能测试工具-并发测试-正版软件下载-使用教程-价格-官方代理商的架构围绕三大核心组件构建,形成完整测试闭环:VirtualUserGenerator(...
- Redis数据类型介绍(redis 数据类型)
-
介绍Redis支持五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sortedset:有序集合)。1、字符串类型概述1.1、数据类型Redis支持...
- RMAN备份监控及优化总结(rman备份原理)
-
今天主要介绍一下如何对RMAN备份监控及优化,这里就不讲rman备份的一些原理了,仅供参考。一、监控RMAN备份1、确定备份源与备份设备的最大速度从磁盘读的速度和磁带写的带度、备份的速度不可能超出这两...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (63)
- oracle批量插入数据 (62)
- oracle事务隔离级别 (53)
- oracle 空为0 (50)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)