package com.org.flashsalesystem.service; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.stereotype.Service; import java.util.*; import java.util.concurrent.TimeUnit; /** * Redis服务类 * 封装Redis的各种操作,包括五种数据类型的应用 */ @Service @Slf4j public class RedisService { @Autowired private RedisTemplate redisTemplate; @Autowired @Qualifier("customStringRedisTemplate") private RedisTemplate stringRedisTemplate; @Autowired private DefaultRedisScript flashSaleScript; @Autowired private DefaultRedisScript lockScript; @Autowired private DefaultRedisScript unlockScript; // ========== String类型操作 ========== /** * 设置字符串值 */ public void set(String key, Object value) { redisTemplate.opsForValue().set(key, value); } /** * 设置纯字符串值(用于Lua脚本兼容) */ public void setString(String key, String value) { stringRedisTemplate.opsForValue().set(key, value); } /** * 设置字符串值并指定过期时间 */ public void set(String key, Object value, long timeout, TimeUnit unit) { redisTemplate.opsForValue().set(key, value, timeout, unit); } /** * 获取字符串值 */ public Object get(String key) { return redisTemplate.opsForValue().get(key); } /** * 安全获取字符串值 */ public String getString(String key) { return stringRedisTemplate.opsForValue().get(key); } /** * 原子递增 */ public Long incr(String key) { return redisTemplate.opsForValue().increment(key); } /** * 原子递增指定步长 */ public Long incrBy(String key, long delta) { return redisTemplate.opsForValue().increment(key, delta); } /** * 原子递减 */ public Long decr(String key) { return redisTemplate.opsForValue().decrement(key); } /** * 原子递减指定步长 */ public Long decrBy(String key, long delta) { return redisTemplate.opsForValue().decrement(key, delta); } /** * 设置键值,仅当键不存在时 */ public Boolean setNx(String key, Object value) { return redisTemplate.opsForValue().setIfAbsent(key, value); } /** * 设置键值和过期时间,仅当键不存在时 */ public Boolean setNx(String key, Object value, long timeout, TimeUnit unit) { return redisTemplate.opsForValue().setIfAbsent(key, value, timeout, unit); } // ========== Hash类型操作 ========== /** * 设置Hash字段值 */ public void hSet(String key, String field, Object value) { redisTemplate.opsForHash().put(key, field, value); } /** * 获取Hash字段值 */ public Object hGet(String key, String field) { return redisTemplate.opsForHash().get(key, field); } /** * 批量设置Hash字段 */ public void hMSet(String key, Map map) { redisTemplate.opsForHash().putAll(key, map); } /** * 批量获取Hash字段值 */ public List hMGet(String key, Collection fields) { return redisTemplate.opsForHash().multiGet(key, fields); } /** * 获取Hash所有字段和值 */ public Map hGetAll(String key) { return redisTemplate.opsForHash().entries(key); } /** * 删除Hash字段 */ public Long hDel(String key, Object... fields) { return redisTemplate.opsForHash().delete(key, fields); } /** * 检查Hash字段是否存在 */ public Boolean hExists(String key, String field) { return redisTemplate.opsForHash().hasKey(key, field); } /** * Hash字段值递增 */ public Long hIncrBy(String key, String field, long delta) { return redisTemplate.opsForHash().increment(key, field, delta); } /** * 获取Hash长度 */ public Long hLen(String key) { return redisTemplate.opsForHash().size(key); } // ========== List类型操作 ========== /** * 从左侧推入元素 */ public Long lPush(String key, Object... values) { return redisTemplate.opsForList().leftPushAll(key, values); } /** * 从右侧推入元素 */ public Long rPush(String key, Object... values) { return redisTemplate.opsForList().rightPushAll(key, values); } /** * 从左侧弹出元素 */ public Object lPop(String key) { return redisTemplate.opsForList().leftPop(key); } /** * 从右侧弹出元素 */ public Object rPop(String key) { return redisTemplate.opsForList().rightPop(key); } /** * 获取列表长度 */ public Long lLen(String key) { return redisTemplate.opsForList().size(key); } /** * 获取列表指定范围的元素 */ public List lRange(String key, long start, long end) { return redisTemplate.opsForList().range(key, start, end); } // ========== Set类型操作 ========== /** * 添加元素到集合 */ public Long sAdd(String key, Object... values) { return redisTemplate.opsForSet().add(key, values); } /** * 从集合中移除元素 */ public Long sRem(String key, Object... values) { return redisTemplate.opsForSet().remove(key, values); } /** * 检查元素是否在集合中 */ public Boolean sIsMember(String key, Object value) { return redisTemplate.opsForSet().isMember(key, value); } /** * 获取集合所有元素 */ public Set sMembers(String key) { return redisTemplate.opsForSet().members(key); } /** * 获取集合大小 */ public Long sCard(String key) { return redisTemplate.opsForSet().size(key); } // ========== ZSet类型操作 ========== /** * 添加元素到有序集合 */ public Boolean zAdd(String key, Object value, double score) { return redisTemplate.opsForZSet().add(key, value, score); } /** * 从有序集合中移除元素 */ public Long zRem(String key, Object... values) { return redisTemplate.opsForZSet().remove(key, values); } /** * 获取有序集合指定范围的元素(按分数排序) */ public Set zRange(String key, long start, long end) { return redisTemplate.opsForZSet().range(key, start, end); } /** * 获取有序集合指定范围的元素(按分数倒序) */ public Set zRevRange(String key, long start, long end) { return redisTemplate.opsForZSet().reverseRange(key, start, end); } /** * 增加有序集合元素的分数 */ public Double zIncrBy(String key, Object value, double delta) { return redisTemplate.opsForZSet().incrementScore(key, value, delta); } /** * 获取有序集合大小 */ public Long zCard(String key) { return redisTemplate.opsForZSet().zCard(key); } // ========== 通用操作 ========== /** * 删除键 */ public Boolean delete(String key) { return redisTemplate.delete(key); } /** * 批量删除键 */ public Long delete(Collection keys) { return redisTemplate.delete(keys); } /** * 检查键是否存在 */ public Boolean exists(String key) { return redisTemplate.hasKey(key); } /** * 设置键的过期时间 */ public Boolean expire(String key, long timeout, TimeUnit unit) { return redisTemplate.expire(key, timeout, unit); } /** * 获取键的剩余过期时间 */ public Long getExpire(String key) { return redisTemplate.getExpire(key); } // ========== Lua脚本操作 ========== /** * 执行秒杀脚本 */ public Long executeFlashSaleScript(String stockKey, int quantity) { log.info("执行秒杀脚本: stockKey={}, quantity={}", stockKey, quantity); try { Long result = stringRedisTemplate.execute(flashSaleScript, Collections.singletonList(stockKey), String.valueOf(quantity)); log.info("秒杀脚本执行结果: result={}", result); return result; } catch (Exception e) { log.error("执行秒杀脚本异常: stockKey={}, quantity={}", stockKey, quantity, e); throw e; } } /** * 执行分布式锁脚本 */ public String executeLockScript(String lockKey, String lockValue, int expireSeconds) { return redisTemplate.execute(lockScript, Collections.singletonList(lockKey), lockValue, String.valueOf(expireSeconds)); } /** * 执行释放锁脚本 */ public Long executeUnlockScript(String lockKey, String lockValue) { return redisTemplate.execute(unlockScript, Collections.singletonList(lockKey), lockValue); } // ========== 发布订阅操作 ========== /** * 发布消息 */ public void publish(String channel, Object message) { redisTemplate.convertAndSend(channel, message); } }