redis keys命令可能导致阻塞问题解决以及单元测试

This commit is contained in:
Chopper 2022-09-29 09:26:18 +08:00
parent 3f8b2f7a30
commit c794bb6a26
3 changed files with 70 additions and 7 deletions

View File

@ -153,7 +153,15 @@ public interface Cache<T> {
* @param pattern 模糊key
* @return 缓存中的数据
*/
List<String> keys(String pattern);
List<Object> keys(String pattern);
/**
* 原生阻塞keys 不推荐使用
*
* @param pattern 模糊key
* @return 缓存中的数据
*/
List<Object> keysBlock(String pattern);
//-----------------------------------------------用于特殊场景redis去重计数---------------------------------------------
@ -211,11 +219,12 @@ public interface Cache<T> {
* @return 计数器结果
*/
Long incr(String key, long liveTime);
/**
* redis 计数器 累加
* 到达liveTime之后该次增加取消即自动-1而不是redis值为空
*
* @param key 为累计的key同一key每次调用则值 +1
* @param key 为累计的key同一key每次调用则值 +1
* @return 计数器结果
*/
Long incr(String key);

View File

@ -90,14 +90,13 @@ public class RedisCache implements Cache {
*/
@Override
public void vagueDel(Object key) {
Set<Object> keys = redisTemplate.keys(key + "*");
List keys = this.keys(key + "*");
redisTemplate.delete(keys);
}
@Override
public void clear() {
Set keys = redisTemplate.keys("*");
List keys = this.keys("*");
redisTemplate.delete(keys);
}
@ -133,8 +132,8 @@ public class RedisCache implements Cache {
* @return 模糊匹配key
*/
@Override
public List<String> keys(String pattern) {
List<String> keys = new ArrayList<>();
public List<Object> keys(String pattern) {
List<Object> keys = new ArrayList<>();
this.scan(pattern, item -> {
//符合条件的key
String key = new String(item, StandardCharsets.UTF_8);
@ -143,6 +142,13 @@ public class RedisCache implements Cache {
return keys;
}
@Override
public List<Object> keysBlock(String pattern) {
Set<Object> set = redisTemplate.keys(pattern);
List<Object> list = new ArrayList<>();
list.addAll(set);
return list;
}
/**
* scan 实现

View File

@ -1,5 +1,6 @@
package cn.lili.test.CacheTest;
import cn.hutool.json.JSONUtil;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.modules.statistics.util.StatisticsSuffix;
@ -122,4 +123,51 @@ class CacheTest {
Assertions.assertTrue(true);
}
@Test
void scanTests() {
for (int i = 0; i < 1000000; i++) {
cache.put("scan" + i, i);
}
Date date = new Date();
System.out.println(JSONUtil.toJsonStr(cache.keys("scan999999*")));
System.out.println("100w数据耗时");
System.out.println(new Date().getTime() - date.getTime());
for (int i = 1000000; i < 5000000; i++) {
cache.put("scan" + i, i);
}
date = new Date();
System.out.println(JSONUtil.toJsonStr(cache.keys("scan999999*")));
System.out.println("600w数据耗时");
System.out.println(new Date().getTime() - date.getTime());
}
// scan 慢些但是在缓存更多的情况下表现更好虽然用时更久但是不会阻塞其他读写
//
//["scan999999"]
//redisTemplate scan 500w数据耗时
//2985
//["scan999999"]
//redisTemplate keys 500w数据耗时
//1073
@Test
void testKsysVsScan() {
Date date = new Date();
System.out.println(JSONUtil.toJsonStr(cache.keys("scan999999*")));
System.out.println("redisTemplate scan 500w数据耗时");
System.out.println(new Date().getTime() - date.getTime());
date = new Date();
System.out.println(JSONUtil.toJsonStr(cache.keysBlock("scan999999*")));
System.out.println("redisTemplate keys 500w数据耗时");
System.out.println(new Date().getTime() - date.getTime());
}
}