相信大家寫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());}}
}