123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- package com.yaoyicloud.config;
- import lombok.RequiredArgsConstructor;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.stereotype.Component;
- import java.util.concurrent.TimeUnit;
- /**
- * Redis 计数器工具类
- */
- @Component
- @RequiredArgsConstructor
- public class RelationCounterRedisUtil {
- // Redis 键前缀(避免与其他缓存键冲突)
- private static final String COUNTER_KEY_PREFIX = "counter:";
- // Redis 模板(注入 String 类型的模板,计数以字符串形式存储)
- private final RedisTemplate<String, String> redisTemplate;
- private static final long DEF_REPORT_TTL = 1 * 60 * 60 * 1000;
- /**
- * 生成 Redis 计数器的完整 key
- * @param relationId 业务关联 ID
- * @return 格式:relation:counter:{relationId}
- */
- private String getCounterKey(Long relationId) {
- return COUNTER_KEY_PREFIX + relationId;
- }
- /**
- * 初始化计数器(若不存在则设置初始值为 0)
- * 注意:通常无需主动调用,increment 方法会自动处理不存在的键
- * @param relationId 业务关联 ID
- */
- public void initCounter(Long relationId) {
- String key = getCounterKey(relationId);
- // 仅当键不存在时设置初始值为 0(避免覆盖已有计数)
- redisTemplate.opsForValue().setIfAbsent(key, "1", DEF_REPORT_TTL, TimeUnit.MILLISECONDS);
- }
- /**
- * 计数器自增 1,并返回自增后的值
- * @param relationId 业务关联 ID
- * @return 自增后的计数(例如:初始为 0,调用后返回 1)
- */
- public int increment(Long relationId) {
- return increment(relationId, 1);
- }
- /**
- * 计数器自增指定步长,并返回自增后的值
- * @param relationId 业务关联 ID
- * @param step 自增步长(正整数)
- * @return 自增后的计数
- */
- public int increment(Long relationId, int step) {
- if (step <= 0) {
- throw new IllegalArgumentException("自增步长必须为正整数");
- }
- String key = getCounterKey(relationId);
- // Redis 的 INCRBY 命令:原子性自增,返回自增后的值
- Long newValue = redisTemplate.opsForValue().increment(key, step);
- return newValue.intValue();
- }
- /**
- * 获取当前计数
- * @param relationId 业务关联 ID
- * @return 当前计数(若键不存在,返回 0)
- */
- public Integer getCount(Long relationId) {
- String key = getCounterKey(relationId);
- String value = redisTemplate.opsForValue().get(key);
- if (value == null) {
- initCounter(relationId);
- return 1;
- }
- return Integer.parseInt(value);
- }
- /**
- * 重置计数器为 0
- * @param relationId 业务关联 ID
- */
- public void reset(Long relationId) {
- String key = getCounterKey(relationId);
- redisTemplate.opsForValue().set(key, "1", DEF_REPORT_TTL, TimeUnit.MILLISECONDS);
- }
- /**
- * 删除计数器(适用于业务结束后清理资源)
- * @param relationId 业务关联 ID
- * @return 是否删除成功(true:键存在且被删除;false:键不存在)
- */
- public boolean delete(Long relationId) {
- String key = getCounterKey(relationId);
- return Boolean.TRUE.equals(redisTemplate.delete(key));
- }
- /**
- * 设置计数器过期时间(避免长期占用 Redis 内存)
- * @param relationId 业务关联 ID
- * @param timeout 过期时间
- * @param unit 时间单位
- */
- public void setExpire(Long relationId, long timeout, TimeUnit unit) {
- String key = getCounterKey(relationId);
- redisTemplate.expire(key, timeout, unit);
- }
- /**
- * 检查计数器是否存在
- * @param relationId 业务关联 ID
- * @return true:存在;false:不存在
- */
- public boolean exists(Long relationId) {
- String key = getCounterKey(relationId);
- return Boolean.TRUE.equals(redisTemplate.hasKey(key));
- }
- }
|