package zs.payment.utils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.ZSetOperations; import org.springframework.stereotype.Repository; import redis.clients.jedis.GeoCoordinate; import redis.clients.jedis.GeoUnit; import redis.clients.jedis.Pipeline; import redis.clients.jedis.Tuple; import redis.clients.jedis.params.SetParams; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * 该redis主要包含支付、订单等数据相关缓存(与资讯池共用) */ @Repository @Slf4j public class RedisUtils { @Value("${pay.redis.master}") private String ecoCluster; public void set(String key, String cont) { set(key, cont, 0); } public void set(String key, String cont, int seconds) { Redis.withCluster(ecoCluster, jedis -> { jedis.set(key, cont); if (seconds > 0) { jedis.expire(key, seconds); } return null; }); } public String get(String key) { return Redis.withCluster(ecoCluster, jedis -> jedis.get(key)); } public String getByKey(String key) { return Redis.withCluster(ecoCluster, jedis -> jedis.get(key)); } public List lRange(String key, long startIndex, long endIndex) { List back = new ArrayList<>(); if (key == null || key.isEmpty()) { return back; } Redis.withCluster(ecoCluster, jedis -> back.addAll(jedis.lrange(key, startIndex, endIndex)) ); return back; } public List mget(List keys) { List back = new ArrayList<>(); if (keys == null || keys.isEmpty()) { return back; } Redis.withCluster(ecoCluster, jedis -> back.addAll(jedis.mget(keys.toArray(new String[0]))) ); return back; } public Long del(String key) { return Redis.withCluster(ecoCluster, jedis -> jedis.del(key)); } public void hset(String key, String field, String cont) { hset(key, field, cont, 0); } public void hset(String key, String field, String cont, int seconds) { Redis.withCluster(ecoCluster, jedis -> { jedis.hset(key, field, cont); if (seconds > 0) { jedis.expire(key, seconds); } return null; }); } public void hmset(String key, Map hash) { hmset(key, hash, 0); } public void hmset(String key, Map hash, int seconds) { Redis.withCluster(ecoCluster, jedis -> { jedis.hmset(key, hash); if (seconds > 0) { jedis.expire(key, seconds); } return null; }); } public Long hincrBy(String key, String field, long value) { return Redis.withCluster(ecoCluster, jedis -> jedis.hincrBy(key, field, value)); } public String hget(String key, String field) { return Redis.withCluster(ecoCluster, jedis -> jedis.hget(key, field)); } public Map hgetAll(String key) { return Redis.withCluster(ecoCluster, jedis -> jedis.hgetAll(key)); } public void hdel(String key, String field) { Redis.withCluster(ecoCluster, jedis -> { jedis.hdel(key, field); return null; }); } /** * * 添加 * redis> SADD myset "one" * @param key * @param members * @return */ public long sadd(String key, String... members) { return Redis.withCluster(ecoCluster, jedis -> jedis.sadd(key, members)); } /** * 删除 * redis> SREM myset "one" * @param key * @param members * @return */ public long srem(String key,String... members){ return Redis.withCluster(ecoCluster,jedis -> jedis.srem(key,members)); } public Set smembers(String key) { return Redis.withCluster(ecoCluster, jedis -> jedis.smembers(key)); } public Boolean sismember(String key,String value){ return Redis.withCluster(ecoCluster,jedis -> jedis.sismember(key,value)); } public long zadd(String key, double score, String member) { return Redis.withCluster(ecoCluster, jedis -> jedis.zadd(key, score, member)); } /** * 向有序集合批量添加元素(使用 Tuple 集合) * @param key 键 * @param tuples 元组集合(包含分数和成员) * @return 成功添加的数量 */ public Long zadd(String key, Set> tuples) { if (tuples == null || tuples.isEmpty()) { return 0L; } long result = 0L; for (ZSetOperations.TypedTuple tuple : tuples) { result=result+ Redis.withCluster(ecoCluster, jedis -> jedis.zadd(key, tuple.getScore(),tuple.getValue())); } return result; } // /** // * 通过管道模式一次性添加多个值 // * // * @param key // * @param list // */ // public void zaddWithPipeline(String key, List list) { // Redis.withCluster(ecoCluster, jedis -> { // Pipeline pipeline = jedis.pipelined(); // for (Object item : list) { // double score = Double.parseDouble(((Map) item).get("userId").toString()); // jedis.zadd(key, score, Strings.toJson(item)); // } // pipeline.syncAndReturnAll(); // }); // } public long llen(String key) { return Redis.withCluster(ecoCluster, jedis -> jedis.llen(key)); } public List lrangeList(String key, int start, int end) { List result = Redis.withCluster(ecoCluster, jedis -> jedis.lrange(key, start, end)); return result != null ? result : new ArrayList<>(); } public void lpush(String key, String... strings) { Redis.withCluster(ecoCluster, jedis -> { jedis.lpush(key, strings); return null; }); } public long rpush(String key, String value) { return Redis.withCluster(ecoCluster, jedis -> jedis.rpush(key, value)); } public String rpop(String key) { return Redis.withCluster(ecoCluster, jedis -> jedis.rpop(key)); } public String lpop(String key) { return Redis.withCluster(ecoCluster, jedis -> jedis.lpop(key)); } public long zrem(String key, String member) { return Redis.withCluster(ecoCluster, jedis -> jedis.zrem(key, member)); } /** * * 返回有序集的元素个数(对应 redisTemplate.opsForZSet().size()) * @param key * @return */ public long zcard(String key) { return Redis.withCluster(ecoCluster, jedis -> jedis.zcard(key)); } public Double zscore(String key, String member) { return Redis.withCluster(ecoCluster, jedis -> jedis.zscore(key, member)); } /** * 倒序(从大到小)获取指定区间内的数据 * * @param key * @param start * @param end * @return */ public Set zrevrange(String key, long start, long end) { return Redis.withCluster(ecoCluster, jedis -> jedis.zrevrange(key, start, end)); } /** * 正序(从小到大)获取指定区间内的数据 * * @param key * @param start * @param end * @return */ public Set zrange(String key, long start, long end) { return Redis.withCluster(ecoCluster, jedis -> jedis.zrange(key, start, end)); } /** * 根据score值,倒序(从大到小)获取指定区间内的数据 * * @param key * @param score * @param psize * @return */ public Set zrevrangeByScore(String key, String score, Integer psize) { return Redis.withCluster(ecoCluster, jedis -> jedis.zrevrangeByScore(key, "(" + score, "-inf", 0, psize)); } /** * 获取score值介于score1和score2之间的数据 * * @param key * @param score1 * @param score2 * @return */ public Set zrangeByScore(String key, String score1, String score2) { return Redis.withCluster(ecoCluster, jedis -> jedis.zrangeByScore(key, score1, score2)); } /** * 设置自增长 * * @param key * @return */ public synchronized long setIncyBy(String key) { return setIncyBy(key, 1L, 0); } /** * 设置自增长 * * @param key * @param num * @return */ public synchronized long setIncyBy(String key, long num) { return setIncyBy(key, num, 0); } /** * 设置自增长 * * @param key * @param num * @param seconds * @return */ public synchronized long setIncyBy(String key, long num, int seconds) { return Redis.withCluster(ecoCluster, jedis -> { long result = jedis.incrBy(key, num); if (seconds > 0) { jedis.expire(key, seconds); } return result; }); } public long setIncy(String key) { return Redis.withCluster(ecoCluster, jedis -> jedis.incr(key)); } public long setDecy(String key) { return Redis.withCluster(ecoCluster, jedis -> jedis.decr(key)); } /** * 按分数从小到大删除指定区域的数据 (对应redisTemplate.opsForZSet().removeRange(key,begin,end))) * * @param key * @param start * @param end * @return */ public long zremrangeByRank(String key, long start, long end) { return Redis.withCluster(ecoCluster, jedis -> jedis.zremrangeByRank(key, start, end)); } /** * setnx实现简单的分布式锁 * * @param key * @param value * @return */ public long setnx(String key, String value) { return setnx(key, value, 0); } /** * setnx实现简单的分布式锁 * * @param key * @param value * @param seconds * @return */ public long setnx(String key, String value, int seconds) { return Redis.withCluster(ecoCluster, jedis -> { long result = jedis.setnx(key, value); if (result == 1 && seconds > 0) { jedis.expire(key, seconds); } return result; }); } /** * SET NX EX 原子命令:仅当Key不存在时设置值,并设置过期时间 * 用于分布式锁的获取 * * @param key 锁的键 * @param value 锁的值(通常是实例ID或服务ID) * @param seconds 过期时间(秒) * @return true 表示成功获得锁,false 表示锁已被占用 */ public boolean setIfAbsent(String key, String value, int seconds) { String result = Redis.withCluster(ecoCluster, jedis -> { // 使用 SET key value NX EX seconds 原子命令 // NX: Only set the key if it does not already exist // EX: Set the specified expire time, in seconds SetParams params = new SetParams().nx().ex(seconds); return jedis.set(key, value, params); }); // 返回 "OK" 表示成功,null 表示键已存在 return "OK".equals(result); } /** * 根据前缀获取所有的key * 例如:pro_* */ public Set getListKey(String prefix) { return Redis.withCluster(ecoCluster, jedis -> jedis.keys(prefix.concat("*"))); } public long geoAdd(String key, double lng, double lat, String member) { return Redis.withCluster(ecoCluster, jedis -> jedis.geoadd(key, lng, lat, member)); } public double geoDist(String key, String member1, String member2) { Double result = Redis.withCluster(ecoCluster, jedis -> jedis.geodist(key, member1, member2, GeoUnit.KM)); return result != null ? result : 0.0; } public List> geoPos(String key, String... members) { List coordinates = Redis.withCluster(ecoCluster, jedis -> jedis.geopos(key, members)); List> coordinateList = new ArrayList<>(); if (coordinates != null && !coordinates.isEmpty()) { for (GeoCoordinate coord : coordinates) { Map location = new HashMap<>(); location.put("lng", coord.getLongitude()); location.put("lat", coord.getLatitude()); coordinateList.add(location); } } return coordinateList; } /** * 设置key的过期时间(对应 redisTemplate.expire()) * @param key 键 * @param timeout 过期时间 * @param unit 时间单位 * @return 是否设置成功 */ public long ttl(String key) { return Redis.withCluster(ecoCluster, jedis -> jedis.ttl(key)); } public Boolean expire(String key, long timeout, TimeUnit unit) { return Redis.withCluster(ecoCluster, jedis -> { // 转换为秒 long seconds = unit.toSeconds(timeout); if (seconds > Integer.MAX_VALUE) { log.warn("过期时间超过Integer最大值,将使用最大值: {}", Integer.MAX_VALUE); seconds = Integer.MAX_VALUE; } jedis.expire(key, (int) seconds); return true; }); } public void set(String key, String cont, int timeout, TimeUnit unit) { Redis.withCluster(ecoCluster, jedis -> { // 转换为秒 long seconds = unit.toSeconds(timeout); if (seconds > Integer.MAX_VALUE) { seconds = Integer.MAX_VALUE; } jedis.set(key, cont); if (seconds > 0) { jedis.expire(key, seconds); } return null; }); } /** * 获取有序集合中指定排名范围内的成员及其分数(按分数从高到低排序) * 对应 redisTemplate.opsForZSet().reverseRangeWithScores() * * @param key 键 * @param start 起始索引(从0开始,包含) * @param end 结束索引(包含,-1表示最后一个) * @return 包含成员和分数的元组集合 */ public Set> zReverseRangeWithScores(String key, long start, long end) { Set tuples = Redis.withCluster(ecoCluster, jedis -> jedis.zrevrangeWithScores(key, start, end)); return tuples.stream() .map(tuple -> ZSetOperations.TypedTuple.of( tuple.getElement(), // 获取元素 tuple.getScore() // 获取分数 )) .collect(Collectors.toSet()); } /** * 使用 Pipeline 批量设置字符串键值对(高性能,适合大量数据) * @param map 包含多个键值对的Map */ public void multiSetWithPipeline(Map map,int timeout, TimeUnit unit) { if (map == null || map.isEmpty()) { return; } Redis.withCluster(ecoCluster, jedis -> { // 创建管道 Pipeline pipeline = jedis.pipelined(); // 将所有set命令添加到管道 for (Map.Entry entry : map.entrySet()) { pipeline.set(entry.getKey(), entry.getValue()); pipeline.expire(entry.getKey(), unit.toSeconds(timeout)); } // 批量执行 pipeline.sync(); return null; }); } public void hmset(String key, Map hash, int timeout, TimeUnit unit) { Redis.withCluster(ecoCluster, jedis -> { jedis.hmset(key, hash); if (timeout > 0) { jedis.expire(key, unit.toSeconds(timeout)); } return null; }); } }