其实用过redis的都明白,redis在真实项目中是很忌讳使用redisTemplate.keys("*")来获取所有key的,这样会使redis在一定时间内卡住。如果redis数据巨大的话,那等待时间很长,几乎可以说是停服了。
使用scan命名
查看lettuce-core源码,我们可以这样操作:
我们通常是使用的集群,所以查看的是AdvancedClusterClientIntegrationTests.java
@Test
void clusterScan() {
RedisAdvancedClusterCommands sync = async.getStatefulConnection().sync();
sync.mset(KeysAndValues.MAP);
Set allKeys = new HashSet<>();
KeyScanCursor scanCursor = null;
do {
if (scanCursor == null) {
scanCursor = sync.scan();
} else {
scanCursor = sync.scan(scanCursor);
}
allKeys.addAll(scanCursor.getKeys());
} while (!scanCursor.isFinished());
assertThat(allKeys).containsAll(KeysAndValues.KEYS);
}
@Test
void clusterScanWithArgs() {
RedisAdvancedClusterCommands sync = async.getStatefulConnection().sync();
sync.mset(KeysAndValues.MAP);
Set allKeys = new HashSet<>();
KeyScanCursor scanCursor = null;
do {
if (scanCursor == null) {
scanCursor = sync.scan(ScanArgs.Builder.matches("a*"));
} else {
scanCursor = sync.scan(scanCursor, ScanArgs.Builder.matches("a*"));
}
allKeys.addAll(scanCursor.getKeys());
} while (!scanCursor.isFinished());
assertThat(allKeys)
.containsAll(KeysAndValues.KEYS.stream().filter(k -> k.startsWith("a")).collect(Collectors.toList()));
}
@Test
void clusterScanStreaming() {
RedisAdvancedClusterCommands sync = async.getStatefulConnection().sync();
sync.mset(KeysAndValues.MAP);
ListStreamingAdapter adapter = new ListStreamingAdapter<>();
StreamScanCursor scanCursor = null;
do {
if (scanCursor == null) {
scanCursor = sync.scan(adapter);
} else {
scanCursor = sync.scan(adapter, scanCursor);
}
} while (!scanCursor.isFinished());
assertThat(adapter.getList()).containsAll(KeysAndValues.KEYS);
}
@Test
void clusterScanStreamingWithArgs() {
RedisAdvancedClusterCommands sync = async.getStatefulConnection().sync();
sync.mset(KeysAndValues.MAP);
ListStreamingAdapter adapter = new ListStreamingAdapter<>();
StreamScanCursor scanCursor = null;
do {
if (scanCursor == null) {
scanCursor = sync.scan(adapter, ScanArgs.Builder.matches("a*"));
} else {
scanCursor = sync.scan(adapter, scanCursor, ScanArgs.Builder.matches("a*"));
}
} while (!scanCursor.isFinished());
assertThat(adapter.getList()).containsAll(
KeysAndValues.KEYS.stream().filter(k -> k.startsWith("a")).collect(Collectors.toList()));
}
参考:http://www.shangdixinxi.com/detail-1230282.html
public boolean tryLock(String lockKey, String clientId, long seconds) {
return redisTemplate.execute((RedisCallback) redisConnection -> {
// Jedis jedis = (Jedis) redisConnection.getNativeConnection();
Object nativeConnection = redisConnection.getNativeConnection();
RedisSerializer stringRedisSerializer = (RedisSerializer) redisTemplate.getKeySerializer();
byte[] keyByte = stringRedisSerializer.serialize(lockKey);
byte[] valueByte = stringRedisSerializer.serialize(clientId);
// lettuce连接包下 redis 单机模式
if (nativeConnection instanceof RedisAsyncCommands) {
RedisAsyncCommands connection = (RedisAsyncCommands) nativeConnection;
RedisCommands commands = connection.getStatefulConnection().sync();
String result = commands.set(keyByte, valueByte, SetArgs.Builder.nx().ex(seconds));
if (LOCK_SUCCESS.equals(result)) {
return true;
}
}
// lettuce连接包下 redis 集群模式
if (nativeConnection instanceof RedisAdvancedClusterAsyncCommands) {
RedisAdvancedClusterAsyncCommands connection = (RedisAdvancedClusterAsyncCommands) nativeConnection;
RedisAdvancedClusterCommands commands = connection.getStatefulConnection().sync();
String result = commands.set(keyByte, valueByte, SetArgs.Builder.nx().ex(seconds));
if (LOCK_SUCCESS.equals(result)) {
return true;
}
}
if (nativeConnection instanceof JedisCommands) {
JedisCommands jedis = (JedisCommands) nativeConnection;
String result = jedis.set(lockKey, clientId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, seconds);
if (LOCK_SUCCESS.equals(result)) {
return true;
}
}
return false;
});
}
// String key="*";
public void ScanAndDel(String key) {
try {
redisTemplate.execute((RedisCallback) redisConnection ->
{
Object nativeConnection = redisConnection.getNativeConnection();
// Jedis
if (nativeConnection instanceof JedisCommands) {
//TODO:
}
// lettuce 单机
if (nativeConnection instanceof RedisAsyncCommands) {
//TODO:
}
// lettuce 集群
if (nativeConnection instanceof RedisAdvancedClusterAsyncCommands) {
RedisAdvancedClusterAsyncCommands connection = (RedisAdvancedClusterAsyncCommands) nativeConnection;
/*RedisAdvancedClusterCommands commands = connection.getStatefulConnection().sync();
KeyScanCursor scanCursor = null;
do {
if (scanCursor == null) {
scanCursor = commands.scan(ScanArgs.Builder.matches(key));
} else {
scanCursor = commands.scan(scanCursor, ScanArgs.Builder.matches(key));
}
List byteKeys = Collections.unmodifiableList(scanCursor.getKeys());
if (byteKeys.size() > 0) {
List keys = new ArrayList<>();
for (Object k : byteKeys) {
keys.add(new String((byte[])k, StandardCharsets.UTF_8));
}
redisTemplate.delete(keys);
}
} while (!scanCursor.isFinished());*/
RedisAdvancedClusterCommands commands = connection.getStatefulConnection().sync();
KeyScanCursor scanCursor = null;
do {
if (scanCursor == null) {
scanCursor = commands.scan(ScanArgs.Builder.matches(matches));
} else {
scanCursor = commands.scan(scanCursor, ScanArgs.Builder.matches(matches));
}
List byteKeys = scanCursor.getKeys();
if (byteKeys.size() > 0) {
byte[][] keys = new byte[byteKeys.size()][];
for (int i = 0; i < byteKeys.size(); i++) {
keys[i] = byteKeys.get(i);
}
commands.del(keys);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
} while (!scanCursor.isFinished());
}
return true;
});
} catch (Exception e) {
}
}
当然,可以是使用ListStreamingAdapter进行操作。