相信大家写redis的时候经常忘记一些指令吧[狗头][狗头],这里整理了一下
一、 String(字符串类型)
1.代码块
// 设置字符串值
stringRedisTemplate.opsForValue().set("key", "value");
// Redis: SET key value// 设置值并设置过期时间(60秒)
stringRedisTemplate.opsForValue().set("key", "value", Duration.ofSeconds(60));
// Redis: SETEX key 60 value// 获取值
String value = stringRedisTemplate.opsForValue().get("key");
// Redis: GET key// 删除键
Boolean isDeleted = stringRedisTemplate.delete("key");
// Redis: DEL key// 判断键是否存在
Boolean exists = stringRedisTemplate.hasKey("key");
// Redis: EXISTS key// 如果键不存在则设置(SETNX)
Boolean successIfAbsent = stringRedisTemplate.opsForValue().setIfAbsent("key", "value");
// Redis: SETNX key value// 如果键存在则设置(SETXX)
Boolean successIfPresent = stringRedisTemplate.opsForValue().setIfPresent("key", "value");
// Redis: SET key value XX// 批量设置多个键值对
Map<String, String> bulkData = new HashMap<>();
bulkData.put("k1", "v1");
bulkData.put("k2", "v2");
stringRedisTemplate.opsForValue().multiSet(bulkData);
// Redis: MSET k1 v1 k2 v2// 批量获取多个键的值
List<String> values = stringRedisTemplate.opsForValue().multiGet(Arrays.asList("k1", "k2"));
// Redis: MGET k1 k2// 自增操作(值必须为整数)
Long newValueAfterIncr = stringRedisTemplate.opsForValue().increment("key");
// Redis: INCR key// 自增指定数值
Long newValueAfterIncrBy = stringRedisTemplate.opsForValue().increment("key", 5);
// Redis: INCRBY key 5// 自减操作(值必须为整数)
Long newValueAfterDecr = stringRedisTemplate.opsForValue().decrement("key");
// Redis: DECR key// 自减指定数值
Long newValueAfterDecrBy = stringRedisTemplate.opsForValue().decrement("key", 3);
// Redis: DECRBY key 3// 获取旧值并设置新值
String oldVal = stringRedisTemplate.opsForValue().getAndSet("key", "newVal");
// Redis: GETSET key newVal// 设置键的过期时间(30秒)
Boolean expireSuccess = stringRedisTemplate.expire("key", Duration.ofSeconds(30));
// Redis: EXPIRE key 30// 获取键的剩余生存时间(TTL)
Long ttl = stringRedisTemplate.getExpire("key");
// Redis: TTL key// 移除键的过期时间(持久化)
Boolean persistSuccess = stringRedisTemplate.persist("key");
// Redis: PERSIST key// 截取字符串的一部分
String range = stringRedisTemplate.opsForValue().get("key", 0, 5);
// Redis: GETRANGE key 0 5// 替换字符串中指定偏移位置的内容
stringRedisTemplate.opsForValue().set("key", "insert", 2);
// Redis: SETRANGE key 2 insert
2.表格
操作 | Java API | 返回类型 | Redis 命令 |
---|
设置值 | stringRedisTemplate.opsForValue().set("key", "value") | void | SET key value |
设置值并过期 | stringRedisTemplate.opsForValue().set("key", "value", Duration.ofSeconds(60)) | void | SETEX key 60 value |
获取值 | stringRedisTemplate.opsForValue().get("key") | String | GET key |
删除键 | stringRedisTemplate.delete("key") | Boolean | DEL key |
判断是否存在 | stringRedisTemplate.hasKey("key") | Boolean | EXISTS key |
设置值如果不存在(SETNX) | stringRedisTemplate.opsForValue().setIfAbsent("key", "value") | Boolean | SETNX key value |
设置值如果存在(SETXX) | stringRedisTemplate.opsForValue().setIfPresent("key", "value") | Boolean | SET key value XX |
批量设置值 | stringRedisTemplate.opsForValue().multiSet(map) | void | MSET k1 v1 k2 v2 |
批量获取值 | stringRedisTemplate.opsForValue().multiGet(Arrays.asList("k1", "k2")) | List<String> | MGET k1 k2 |
自增 | stringRedisTemplate.opsForValue().increment("key") | Long | INCR key |
自增指定值 | stringRedisTemplate.opsForValue().increment("key", 5) | Long | INCRBY key 5 |
自减 | stringRedisTemplate.opsForValue().decrement("key") | Long | DECR key |
自减指定值 | stringRedisTemplate.opsForValue().decrement("key", 3) | Long | DECRBY key 3 |
获取旧值并设置新值 | stringRedisTemplate.opsForValue().getAndSet("key", "newVal") | String | GETSET key newVal |
设置过期时间 | stringRedisTemplate.expire("key", Duration.ofSeconds(30)) | Boolean | EXPIRE key 30 |
获取剩余 TTL | stringRedisTemplate.getExpire("key") | Duration | TTL key |
持久化(去掉过期时间) | stringRedisTemplate.persist("key") | Boolean | PERSIST key |
截取字符串 | stringRedisTemplate.opsForValue().get("key", 0, 5) | String | GETRANGE key 0 5 |
替换指定位置的字符串 | stringRedisTemplate.opsForValue().set("key", "abc", 2) | void | SETRANGE key 2 abc |
二、List(列表类型)
1.代码块
// 左侧插入元素(头插)
Long sizeAfterLeftPush = stringRedisTemplate.opsForList().leftPush("list", "a");
// Redis: LPUSH list a// 右侧插入元素(尾插)
Long sizeAfterRightPush = stringRedisTemplate.opsForList().rightPush("list", "b");
// Redis: RPUSH list b// 左侧弹出元素(头删)
String leftPopValue = stringRedisTemplate.opsForList().leftPop("list");
// Redis: LPOP list// 右侧弹出元素(尾删)
String rightPopValue = stringRedisTemplate.opsForList().rightPop("list");
// Redis: RPOP list// 阻塞式左侧弹出元素(等待最多10秒)
String blockedLeftPop = stringRedisTemplate.opsForList().leftPop("list", Duration.ofSeconds(10));
// Redis: BLPOP list 10// 获取列表指定范围内的元素(0 到 -1 表示全部)
List<String> elements = stringRedisTemplate.opsForList().range("list", 0, -1);
// Redis: LRANGE list 0 -1// 获取列表长度
Long listSize = stringRedisTemplate.opsForList().size("list");
// Redis: LLEN list// 设置指定索引位置的值
stringRedisTemplate.opsForList().set("list", 1, "newVal");
// Redis: LSET list 1 newVal// 删除指定值的元素(删除第一个等于 "val" 的元素)
Long removedCount = stringRedisTemplate.opsForList().remove("list", 1, "val");
// Redis: LREM list 1 val
2.表格
操作 | Java API | 返回类型 | Redis 命令 |
---|
左入队 | stringRedisTemplate.opsForList().leftPush("list", "a") | Long | LPUSH list a |
右入队 | stringRedisTemplate.opsForList().rightPush("list", "b") | Long | RPUSH list b |
左出队 | stringRedisTemplate.opsForList().leftPop("list") | String | LPOP list |
右出队 | stringRedisTemplate.opsForList().rightPop("list") | String | RPOP list |
阻塞左出队 | stringRedisTemplate.opsForList().leftPop("list", Duration.ofSeconds(10)) | String | BLPOP list 10 |
获取范围内元素 | stringRedisTemplate.opsForList().range("list", 0, -1) | List<String> | LRANGE list 0 -1 |
获取列表长度 | stringRedisTemplate.opsForList().size("list") | Long | LLEN list |
设置指定位置的值 | stringRedisTemplate.opsForList().set("list", 1, "newVal") | void | LSET list 1 newVal |
删除指定元素 | stringRedisTemplate.opsForList().remove("list", 1, "val") | Long | LREM list 1 val |
三、Hash(哈希类型)
1.代码块
// 设置字段值
stringRedisTemplate.opsForHash().put("hash", "field", "val");
// Redis: HSET hash field val// 获取字段值
Object fieldValue = stringRedisTemplate.opsForHash().get("hash", "field");
// Redis: HGET hash field// 获取所有字段和值
Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries("hash");
// Redis: HGETALL hash// 获取所有字段名
Set<Object> keys = stringRedisTemplate.opsForHash().keys("hash");
// Redis: HKEYS hash// 获取所有字段值
List<Object> values = stringRedisTemplate.opsForHash().values("hash");
// Redis: HVALS hash// 判断字段是否存在
Boolean hasField = stringRedisTemplate.opsForHash().hasKey("hash", "field");
// Redis: HEXISTS hash field// 删除字段
Long deletedCount = stringRedisTemplate.opsForHash().delete("hash", "field");
// Redis: HDEL hash field// 批量设置字段值
Map<String, String> map = new HashMap<>();
map.put("field1", "value1");
map.put("field2", "value2");
stringRedisTemplate.opsForHash().putAll("hash", map);
// Redis: HMSET hash field1 value1 field2 value2// 批量获取字段值
List<Object> multiGetValues = stringRedisTemplate.opsForHash().multiGet("hash", Arrays.asList("field1", "field2"));
// Redis: HMGET hash field1 field2// 字段值自增(数值必须为整数)
Long incrementedValue = stringRedisTemplate.opsForHash().increment("hash", "field", 1L);
// Redis: HINCRBY hash field 1
2.表格
操作 | Java API | 返回类型 | Redis 命令 |
---|
设置字段值 | stringRedisTemplate.opsForHash().put("hash", "field", "val") | void | HSET hash field val |
获取字段值 | stringRedisTemplate.opsForHash().get("hash", "field") | Object | HGET hash field |
获取所有字段 | stringRedisTemplate.opsForHash().entries("hash") | Map<Object, Object> | HGETALL hash |
获取所有字段名 | stringRedisTemplate.opsForHash().keys("hash") | Set<Object> | HKEYS hash |
获取所有字段值 | stringRedisTemplate.opsForHash().values("hash") | List<Object> | HVALS hash |
判断字段是否存在 | stringRedisTemplate.opsForHash().hasKey("hash", "field") | Boolean | HEXISTS hash field |
删除字段 | stringRedisTemplate.opsForHash().delete("hash", "field") | Long | HDEL hash field |
批量设置字段值 | stringRedisTemplate.opsForHash().putAll("hash", map) | void | HMSET hash field1 val1 ... |
批量获取字段值 | stringRedisTemplate.opsForHash().multiGet("hash", Arrays.asList("f1", "f2")) | List<Object> | HMGET hash f1 f2 |
字段值自增 | stringRedisTemplate.opsForHash().increment("hash", "field", 1) | Long | HINCRBY hash field 1 |
四、Set(集合类型)
1.代码块
// 添加元素到集合
Long addCount = stringRedisTemplate.opsForSet().add("set", "a");
// Redis: SADD set a// 删除集合中的元素
Long removeCount = stringRedisTemplate.opsForSet().remove("set", "a");
// Redis: SREM set a// 判断某个元素是否存在于集合中
Boolean isMember = stringRedisTemplate.opsForSet().isMember("set", "a");
// Redis: SISMEMBER set a// 获取集合中的所有成员
Set<String> members = stringRedisTemplate.opsForSet().members("set");
// Redis: SMEMBERS set// 获取集合的元素个数
Long setSize = stringRedisTemplate.opsForSet().size("set");
// Redis: SCARD set// 随机弹出一个元素(并从集合中删除)
String poppedElement = stringRedisTemplate.opsForSet().pop("set");
// Redis: SPOP set// 随机获取一个元素(不删除)
String randomElement = stringRedisTemplate.opsForSet().randomMember("set");
// Redis: SRANDMEMBER set
2.表格
操作 | Java API | 返回类型 | Redis 命令 |
---|
添加元素 | stringRedisTemplate.opsForSet().add("set", "a") | Long | SADD set a |
删除元素 | stringRedisTemplate.opsForSet().remove("set", "a") | Long | SREM set a |
判断是否存在 | stringRedisTemplate.opsForSet().isMember("set", "a") | Boolean | SISMEMBER set a |
获取所有元素 | stringRedisTemplate.opsForSet().members("set") | Set<String> | SMEMBERS set |
获取元素个数 | stringRedisTemplate.opsForSet().size("set") | Long | SCARD set |
随机弹出一个元素 | stringRedisTemplate.opsForSet().pop("set") | String | SPOP set |
随机获取一个元素(不删除) | stringRedisTemplate.opsForSet().randomMember("set") | String | SRANDMEMBER set |
五、ZSet(有序集合)
1.代码块
// 添加元素及分数
Boolean addSuccess = stringRedisTemplate.opsForZSet().add("zset", "member", 100);
// Redis: ZADD zset 100 member// 删除元素
Long removeCount = stringRedisTemplate.opsForZSet().remove("zset", "member");
// Redis: ZREM zset member// 获取成员的排名(按分数升序)
Long rank = stringRedisTemplate.opsForZSet().rank("zset", "member");
// Redis: ZRANK zset member// 获取成员的排名(按分数降序)
Long reverseRank = stringRedisTemplate.opsForZSet().reverseRank("zset", "member");
// Redis: ZREVRANK zset member// 获取成员的分数
Double score = stringRedisTemplate.opsForZSet().score("zset", "member");
// Redis: ZSCORE zset member// 增加成员的分数
Double newScore = stringRedisTemplate.opsForZSet().incrementScore("zset", "member", 5);
// Redis: ZINCRBY zset 5 member// 获取指定范围内的成员(按分数升序,索引 0 到 10)
Set<String> rangeMembers = stringRedisTemplate.opsForZSet().range("zset", 0, 10);
// Redis: ZRANGE zset 0 10// 获取指定范围内的成员(按分数降序,索引 0 到 10)
Set<String> reverseRangeMembers = stringRedisTemplate.opsForZSet().reverseRange("zset", 0, 10);
// Redis: ZREVRANGE zset 0 10
2.表格
操作 | Java API | 返回类型 | Redis 命令 |
---|
添加元素及分数 | stringRedisTemplate.opsForZSet().add("zset", "member", 100) | Boolean | ZADD zset 100 member |
删除元素 | stringRedisTemplate.opsForZSet().remove("zset", "member") | Long | ZREM zset member |
获取排名(正序) | stringRedisTemplate.opsForZSet().rank("zset", "member") | Long | ZRANK zset member |
获取排名(倒序) | stringRedisTemplate.opsForZSet().reverseRank("zset", "member") | Long | ZREVRANK zset member |
获取成员分数 | stringRedisTemplate.opsForZSet().score("zset", "member") | Double | ZSCORE zset member |
增加分数 | stringRedisTemplate.opsForZSet().incrementScore("zset", "member", 5) | Double | ZINCRBY zset 5 member |
获取指定范围(正序) | stringRedisTemplate.opsForZSet().range("zset", 0, 10) | Set<String> | ZRANGE zset 0 10 |
获取指定范围(倒序) | stringRedisTemplate.opsForZSet().reverseRange("zset", 0, 10) | Set<String> | ZREVRANGE zset 0 10 |
六、BitMap(位图)
1.代码块
// 设置指定偏移位的 bit 值为 1
stringRedisTemplate.opsForValue().setBit("bitmap", 1, true);
// Redis: SETBIT bitmap 1 1// 获取指定偏移位的 bit 值
Boolean bit = stringRedisTemplate.opsForValue().getBit("bitmap", 1);
// Redis: GETBIT bitmap 1// 统计所有为 1 的 bit 数量
Long count = stringRedisTemplate.execute((RedisConnection connection) ->connection.bitCount("bitmap".getBytes()));
// Redis: BITCOUNT bitmap// 对两个 bitmap 做 AND 运算并将结果保存到新 key
Long resultLength = stringRedisTemplate.execute((RedisConnection connection) ->connection.bitOpAnd("result".getBytes(), "bitmap1".getBytes(), "bitmap2".getBytes()));
// Redis: BITOP AND result bitmap1 bitmap2// 获取 bitmap 底层字符串的字节长度(即占用多少字节)
Long size = stringRedisTemplate.opsForValue().size("bitmap");
// Redis: STRLEN bitmap// 获取 bitmap 的某段二进制范围(可用于分页或分析)
String partial = stringRedisTemplate.opsForValue().get("bitmap", 0, 5);
// Redis: GETRANGE bitmap 0 5
2.表格
操作 | Java API | 返回类型 | Redis 命令 |
---|
设置指定偏移位的 bit 值(1 或 0) | stringRedisTemplate.opsForValue().setBit("bitmap", 1, true) | Boolean | SETBIT bitmap 1 1 |
获取指定偏移位的 bit 值 | stringRedisTemplate.opsForValue().getBit("bitmap", 1) | Boolean | GETBIT bitmap 1 |
统计所有为 1 的 bit 数量(位数统计) | stringRedisTemplate.execute((RedisConnection connection) -> connection.bitCount("bitmap".getBytes())); | Long | BITCOUNT bitmap |
对多个 bitmap 做位运算(AND/OR/XOR/NOT)并保存结果 | stringRedisTemplate.execute((RedisConnection connection) -> connection.bitOpAnd("dest".getBytes(), "bitmap1".getBytes(), "bitmap2".getBytes())); | Long | BITOP AND dest bitmap1 bitmap2 |
获取 bitmap 占用的字节数(即底层字符串长度) | stringRedisTemplate.opsForValue().size("bitmap") | Long | STRLEN bitmap |
获取 bitmap 指定范围内的二进制数据(可用来做分页处理) | stringRedisTemplate.opsForValue().get("bitmap", offsetStart, offsetEnd) | String | GETRANGE bitmap offset_start offset_end |
执行位运算后返回结果(不保存) | stringRedisTemplate.execute((RedisConnection connection) -> connection.bitOp(BitOperation.OR, null, key1.getBytes(), key2.getBytes())) | byte[] | BITOP OR dest key1 key2 |
七、HyperLogLog
1.代码块
// 添加单个元素到 HyperLogLog
Long addResult = stringRedisTemplate.opsForHyperLogLog().add("hll", "val1");
// Redis: PFADD hll val1// 添加多个元素到 HyperLogLog
Long addMultiResult = stringRedisTemplate.opsForHyperLogLog().add("hll", new String[]{"val1", "val2", "val3"});
// Redis: PFADD hll val1 val2 val3// 获取 HyperLogLog 中估算的唯一元素数量(基数估计值)
Long size = stringRedisTemplate.opsForHyperLogLog().size("hll");
// Redis: PFCOUNT hll// 合并多个 HyperLogLog 到一个新的 HyperLogLog 中
stringRedisTemplate.opsForHyperLogLog().union("hllUnion", new String[]{"hll1", "hll2"});
// Redis: PFMERGE hllUnion hll1 hll2// 获取合并后 HyperLogLog 中估算的唯一元素数量
Long unionSize = stringRedisTemplate.opsForHyperLogLog().size("hllUnion");
// Redis: PFCOUNT hllUnion// 对多个 HyperLogLog 进行基数估计,无需显式合并
Long multiCount = stringRedisTemplate.opsForHyperLogLog().size(new String[]{"hll1", "hll2"});
// Redis: PFCOUNT hll1 hll2
2.表格
操作 | Java API | 返回类型 | Redis 命令 |
---|
添加单个元素 | stringRedisTemplate.opsForHyperLogLog().add("hll", "val1") | Long | PFADD hll val1 |
添加多个元素 | stringRedisTemplate.opsForHyperLogLog().add("hll", new String[]{"val1", "val2"}) | Long | PFADD hll val1 val2 |
获取基数估计值(单个) | stringRedisTemplate.opsForHyperLogLog().size("hll") | Long | PFCOUNT hll |
获取多个 HLL 的合并基数估计值 | stringRedisTemplate.opsForHyperLogLog().size(new String[]{"hll1", "hll2"}) | Long | PFCOUNT hll1 hll2 |
合并多个 HLL 到新 HLL | stringRedisTemplate.opsForHyperLogLog().union("hllUnion", new String[]{"hll1", "hll2"}) | Long | PFMERGE hllUnion hll1 hll2 |
八、GEO(地理位置)
1.代码块
// 添加地理位置
Long addResult = stringRedisTemplate.opsForGeo().add("geo", new Point(116.40, 39.90), "beijing");
// Redis: GEOADD geo 116.40 39.90 beijing// 获取两个位置之间的距离,默认单位为米
Distance distance = stringRedisTemplate.opsForGeo().distance("geo", "beijing", "shanghai");
// Redis: GEODIST geo beijing shanghai// 获取指定地点周围一定范围内的位置(例如:以北京为中心,半径100公里)
Circle circle = new Circle(new Point(116.40, 39.90), new Distance(100, Metrics.KILOMETERS));
GeoResults<RedisGeoCommands.GeoLocation<String>> nearbyPlaces = stringRedisTemplate.opsForGeo().radius("geo", circle);
// Redis: GEORADIUS geo 116.40 39.90 100 km// 获取某个位置的经纬度坐标
List<Point> points = stringRedisTemplate.opsForGeo().position("geo", "beijing");
// Redis: GEOPOS geo beijing
2.表格
操作 | Java API | 返回类型 | Redis 命令 |
---|
添加地理位置 | stringRedisTemplate.opsForGeo().add("geo", new Point(116.40, 39.90), "beijing") | Long | GEOADD geo 116.40 39.90 beijing |
获取两个位置距离 | stringRedisTemplate.opsForGeo().distance("geo", "beijing", "shanghai") | Distance | GEODIST geo beijing shanghai |
获取某地附近的位置 | stringRedisTemplate.opsForGeo().radius("geo", new Circle(new Point(116.40, 39.90), new Distance(100, Metrics.KILOMETERS))) | GeoResults <RedisGeoCommands. GeoLocation<String>> | GEORADIUS geo 116.40 39.90 100 km |
获取位置经纬度 | stringRedisTemplate.opsForGeo().position("geo", "beijing") | List<Point> | GEOPOS geo beijing |
九、Stream(流)
1.代码块
// 添加记录到 Stream 中
Map<String, String> map = new HashMap<>();
map.put("field1", "val1");
RecordId recordId = stringRedisTemplate.opsForStream().add("mystream", map);
// Redis: XADD mystream * field1 val1// 读取 Stream 中的记录
List<MapRecord<String, Object, Object>> records = stringRedisTemplate.opsForStream().read(StreamReadOptions.empty().count(1),StreamOffset.fromStart("mystream"));
// Redis: XRANGE mystream - + COUNT 1// 创建消费者组
try {stringRedisTemplate.opsForStream().createGroup("mystream", ReadOffset.latest(), "mygroup");
} catch (Exception e) {// 可能会抛出异常如果组已存在
}
// Redis: XGROUP CREATE mystream mygroup $ MKSTREAM// 使用消费者组读取 Stream 中的新消息
List<MapRecord<String, Object, Object>> groupRecords = stringRedisTemplate.opsForStream().read(Consumer.from("mygroup", "consumer1"),StreamReadOptions.empty(),StreamOffset.create("mystream", ReadOffset.lastConsumed()));
// Redis: XREADGROUP GROUP mygroup consumer1 STREAMS mystream >
2.表格
操作 | Java API | 返回类型 | Redis 命令 |
---|
添加记录 | stringRedisTemplate.opsForStream().add("mystream", map) | RecordId | XADD mystream * field1 val1 |
读取记录 | stringRedisTemplate.opsForStream().read(StreamReadOptions.empty().count(1), StreamOffset.fromStart("mystream")) | List<MapRecord<String, Object, Object>> | XRANGE mystream - + COUNT 1 |
创建消费者组 | stringRedisTemplate.opsForStream().createGroup("mystream", ReadOffset.latest(), "mygroup") | void | XGROUP CREATE mystream mygroup $ MKSTREAM |
消费组读取 | stringRedisTemplate.opsForStream().read(Consumer.from("mygroup", "consumer1"), StreamReadOptions.empty(), StreamOffset.create("mystream", ReadOffset.lastConsumed())) | List<MapRecord<String, Object, Object>> | XREADGROUP GROUP mygroup consumer1 STREAMS mystream > |
十、管道批次化工具类
package com.quick.utils;import com.quick.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.StringRedisTemplate;import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;/*** @program: quick-pick* @description: redis 管道批量操作* @author: bluefoxyu* @date: 2025-06-17 00:14**/@Slf4j
public class RedisPipelineUtil {/*** 批量执行 Redis 管道操作,固定先删除旧 key,再新增内容,再设置过期时间,带异常捕获和清理。 TODO 这个只做参考案例不做调用** @param stringRedisTemplate Redis 操作模板* @param dataList 需要批量操作的数据集合* @param keyPrefix Redis key 前缀(用作拼接 key)* 你操作时先 del,再 add(或其它写操作),再 expire* @param <T> 数据类型泛型*/public static <T> void batchDelAddExpire(StringRedisTemplate stringRedisTemplate,List<T> dataList,String keyPrefix) {if (dataList == null || dataList.isEmpty()) {return;}try {Object object =new Object(); // 需要存的数据// 一次性stringRedisTemplate.executePipelined((RedisCallback<Object>) connection -> {for (T fav : dataList) {long userId = 1L; // 用户ID用于拼接 TODO 实际上业务场景中得从dataList的fav中取出来,删除对应用户的String redisKey = keyPrefix + userId;// 先删除原来的 Redis 数据connection.del(redisKey.getBytes());// 这个 .getBytes() 是为了把字符串转换成字节数组(byte[]),因为底层 Redis 连接的 API 需要的是字节数组作为参数。connection.sAdd(redisKey.getBytes(), object.toString().getBytes());// 3. 设置随机过期时间防雪崩connection.expire(redisKey.getBytes(),TimeUnit.DAYS.toSeconds(7) + ThreadLocalRandom.current().nextInt(86400));}return null;});// 分批次int batchSize = 100;for (int i = 0; i < dataList.size(); i += batchSize) {List<T> batch = dataList.subList(i, Math.min(i + batchSize, dataList.size()));stringRedisTemplate.executePipelined((RedisCallback<?>) connection -> {for (T fav : batch) {// 执行操作}return null;});}} catch (Exception ex) {log.error("将数据放进Redis任务异常", ex);} finally {// 清理集合,加速 GCdataList.clear();}}/*** 使用 StringRedisTemplate 按 key 模式批量删除 Redis 键** @param stringRedisTemplate 注入的 StringRedisTemplate* @param keyPattern 通配符模式,如 "user:session:*"* @param batchSize 每批删除的 key 数量*/public static void batchDeleteByPattern(StringRedisTemplate stringRedisTemplate, String keyPattern, int batchSize) {// 构建 scan 配置,支持模糊匹配 + 每批数量控制ScanOptions options = ScanOptions.scanOptions().match(keyPattern).count(batchSize).build();try (Cursor<byte[]> cursor = Objects.requireNonNull(stringRedisTemplate.getConnectionFactory()).getConnection().scan(options)) {List<String> keys = new ArrayList<>(batchSize);while (cursor.hasNext()) {// 将 byte[] 转成 String keyString key = stringRedisTemplate.getStringSerializer().deserialize(cursor.next());if (key != null) {keys.add(key);}// 每达到一批就批量删除if (keys.size() >= batchSize) {stringRedisTemplate.delete(keys);keys.clear();}}// 删除最后不足一批的if (!keys.isEmpty()) {stringRedisTemplate.delete(keys);}} catch (Exception e) {System.err.println("Redis 扫描删除异常: " + e.getMessage());throw new BaseException("Redis 扫描删除异常, 异常信息为:" + e.getMessage());}}
}