秒杀系统Redis中的Key设计

概述

在秒杀系统中通常会需要将key存储到redis中,key的一般设计通常通过类名:midKey+后缀key的形式构成,一般情况下在加个过期时间,大概key设计,通常情况下会将key设计为一个接口一个抽象类多个实现类的形式,如下

demo

在这里插入图片描述
接口中有过期时间和前缀prefix两个方法,抽象类实现整个接口,重写prefix为类名+前缀prefix的形式,这样做的目的在于set或get参数时,可以通过传入实现类用接口就可以接,从接口中获取具体的前缀、过期时间,存放到redis中,更易于拓展

public interface KeyPrefix {
		
	int expireSeconds();
	
	String getPrefix();
	
}

抽象类则实现接口并重写getPrefix方法

在这里插入图片描述

其中,抽象类这个方法是设置过期时间的随机值,用于防止缓存雪崩
在这里插入图片描述

具体代码如下

public abstract class BasePrefix implements KeyPrefix{
	
	private int expireSeconds;
	
	private String prefix;
	
	public BasePrefix(String prefix) {//0代表永不过期
		this(0, prefix);
	}
	
	public BasePrefix(int expireSeconds, String prefix) {
		this.expireSeconds = expireSeconds;
		this.prefix = prefix;
	}
	
	public BasePrefix(int expireSeconds, boolean addRandom, String prefix) {
		if(addRandom) {
			Random random = new Random(System.currentTimeMillis());
			int extend = expireSeconds / 5;
			int ran = random.nextInt(extend);
			int finalExtend = extend / 2 - ran;
			this.expireSeconds = expireSeconds + finalExtend;
		} else {
			this.expireSeconds = expireSeconds;
		}
		this.prefix = prefix;
	}

	
	public int expireSeconds() {//默认0代表永不过期
		return expireSeconds;
	}

	public String getPrefix() {
		String className = getClass().getSimpleName();
		//类名:prefix
		return className+":" + prefix;
	}

}

GoodsKey则具体实现了抽象类

public class GoodsKey extends BasePrefix {
	
	public GoodsKey(int expireSeconds, boolean addRandom, String prefix) {
		
		super(expireSeconds, addRandom, prefix);
	}

}

RedisUtil则将相应的类型转换为String并存到redis中
在这里插入图片描述
或是将String类型转换为bean返回
在这里插入图片描述

@Component
public class RedisUtil {

    @Autowired
    private RedisTemplate redisTemplate;

    public <T> boolean set(KeyPrefix prefix, String key, T value) {

        try {
            String str = beanToString(value);
            if (StringUtils.isEmpty(str)){
                return false;
            }
            //GoodKey:prefix+key 类名:prefix+key
            String realKey = prefix.getPrefix() + key;
            if (prefix.expireSeconds()<=0){
                redisTemplate.opsForValue().set(realKey,str);
            }else {
                redisTemplate.opsForValue().set(realKey,str,prefix.expireSeconds(), TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    public <T> T get(KeyPrefix prefix, String key, Class<T> clazz) {

        try {
            String realKey = prefix.getPrefix() + key;
            String str =(String)redisTemplate.opsForValue().get(realKey);
            T t = stringToBean(str, clazz);
            return t;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T stringToBean(String str, Class<T> clazz) throws JsonProcessingException {
        if (str == null || str.length() == 0 || clazz == null) {
            return null;
        }
        if (clazz == int.class || clazz == Integer.class) {
            return (T) Integer.valueOf(str);
        } else if (clazz == String.class) {
            return (T) str;
        } else if (clazz == long.class || clazz == Long.class) {
            return (T) Long.valueOf(str);
        } else {
            return new ObjectMapper().readValue(str,clazz);
        }
    }

    public static <T> String beanToString(T value) throws JsonProcessingException {
        if (value == null) {
            return null;
        }
        Class<?> clazz = value.getClass();
        if (clazz == int.class || clazz == Integer.class) {
            return "" + value;
        } else if (clazz == String.class) {
            return (String) value;
        } else if (clazz == long.class || clazz == Long.class) {
            return "" + value;
        } else {
            return new ObjectMapper().writeValueAsString(value);
        }
    }

}

来做个测试吧

@RequestMapping("redis")
@RestController
public class TestController {

    @Autowired
    private RedisUtil redisUtil;

    @GetMapping("set")
    public void set(){

        redisUtil.set(new GoodsKey(60,true,"gl"),"",String.class);

    }

    @GetMapping("get")
    public void get(){

        String gl = redisUtil.get(new GoodsKey(60, true, "gl"), "", String.class);
        System.out.println("gl:"+gl);

    }

}

可以看到相应的值了,如此
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值