秒杀06--通用缓存key的设计与封装

秒杀06–通用缓存key的设计与封装

为什么要这个通用缓存Key?

当项目中的模块越来越多的时候,需要存的缓存也越来越多,比如商品Id,订单Id,用户id等,此时若是id出现重复,将给系统带来错误,对于一个系统来说这肯定是不行的
那么使用KeyPrefix来更好的操作和管理缓存中对应的key。给不同模块的key带有一个前缀。

不加前缀的情况:


	public <T> boolean set(String key,T value){
		Jedis jedis=null;
		//在JedisPool里面取得Jedis
		try {
			jedis=jedisPool.getResource();
			//将T类型转换为String类型
			String s=beanToString(value);
			if(s==null) {
				return false;
			}
			jedis.set(key, s);
			return true;
		}finally {
			returnToPool(jedis);
		}
	}

解决覆盖key的办法:
将前缀+一个key一起作为一个redis里面真正的key,这样不同模块之间就不会重复。

好处不同功能或者不同模块的前缀不同,即使有同名key出现,那么前缀不同,并不会引起key冲突被其他功能覆盖的情况

使用一个模板模式来封装:
在这里插入图片描述
接口:

public interface KeyPrefix {
//做缓存的前缀接口 
    
     //有效期	
	public int expireSeconds();
	//前缀
	public String getPrefix();
	
}

BasePrefix 抽象类:简单的实现一下KeyPrefix,定义成抽象类原因,防止不小心被创建,我们不希望BasePrefix被实例化,因为抽象类不允许实例化。我们只希望它被继承。不同模块的前缀类都继承他

package com.imooc.miaosha.redis;
//定义成抽象类
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 int expireSeconds() {//默认0代表永不过期
		return expireSeconds;
	}
    
    //前缀为类名:+prefix
	public String getPrefix() {
		String className = getClass().getSimpleName();
		return className+":" + prefix;
	}

}

注意:该类2种不同构造方法:用于继承。一个只带前缀名,一个带前缀名和过期时间。当实现public BasePrefix(String prefix)的时候,我们将默认这个key不会失效,因为有一些场景,我们不希望key失效,但是有些场景我们需要设置key的合适的有效期。

具体实现类:

用户UserKey只去继承了super(prefix),即public BasePrefix(String prefix),那么代表user的key的过期时间为不会过期。

public class UserKey extends BasePrefix{

	private UserKey(String prefix) {
		super(prefix);
	}
	public static UserKey getById = new UserKey("id");
	public static UserKey getByName = new UserKey("name");
}

秒杀用户的MiaoshaUserKey ,继承了super(expireSeconds,prefix),可以设置有效期时间为2天(根据自己的实际来设置)。

public class MiaoshaUserKey extends BasePrefix{

	public static final int TOKEN_EXPIRE = 3600*24 * 2;
	private MiaoshaUserKey(int expireSeconds, String prefix) {
		super(expireSeconds, prefix);
	}
	public static MiaoshaUserKey token = new MiaoshaUserKey(TOKEN_EXPIRE, "tk");
}

具体实现类的具体使用场景:


     /**
	 *避免key被不同类的数据覆盖 
	 *使用Prefix前缀-->不同类别的缓存,用户、部门、
	 */
    @RequestMapping("/redis/get")
    @ResponseBody
    public Result<User> redisGet() {
    	User  user  = redisService.get(UserKey.getById, ""+1, User.class);
        return Result.success(user);
    }
    
    @RequestMapping("/redis/set")
    @ResponseBody
    public Result<Boolean> redisSet() {
    	User user  = new User();
    	user.setId(1);
    	user.setName("1111");
    	redisService.set(UserKey.getById, ""+1, user);//UserKey:id1
        return Result.success(true);
    }
    

完善后的get和set缓存的Key值的方法:

@Autowired
	JedisPool jedisPool;
	
	/**
	 * 获取当个对象
	 * */
	public <T> T get(KeyPrefix prefix, String key,  Class<T> clazz) {
		 Jedis jedis = null;
		 try {
			 jedis =  jedisPool.getResource();
			 //生成真正的key, className+":"+prefix;  BasePrefix:id1
			 String realKey  = prefix.getPrefix() + key;
			 String  str = jedis.get(realKey);
			 T t =  stringToBean(str, clazz);
			 return t;
		 }finally {
			  returnToPool(jedis);
		 }
	}
	
	/**
	 * 设置对象
	 * */
	public <T> boolean set(KeyPrefix prefix, String key,  T value) {
		 Jedis jedis = null;
		 try {
			 jedis =  jedisPool.getResource();
			 String str = beanToString(value);
			 if(str == null || str.length() <= 0) {
				 return false;
			 }
			//生成真正的key
			 String realKey  = prefix.getPrefix() + key;
			 int seconds =  prefix.expireSeconds();
			 if(seconds <= 0) {
				 jedis.set(realKey, str);
			 }else {
				 jedis.setex(realKey, seconds, str);
			 }
			 return true;
		 }finally {
			  returnToPool(jedis);
		 }
	}
	

感谢:
参考:https://blog.csdn.net/Brad_PiTt7/article/details/90610097

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读