因为再使用redis的过程中,开发A设置了 name-"zhaojun" 开发B设置了name-"zk",这就造成了A,B
一个人的数据丢失,会存在key 的冲突,冲突了又只有在获取的时候才知道,这种问题还再排查一遍.为了避免这种情况,我们在key的前面就上两层的字符串,避免key的重复,同时对key的存在时间进行一层封装.具体看代码:
1.接口的封装
public interface KeyPrefix {
int expireSeconds();
String getPrefix();
}
2.抽象类的封装
/**
* 为了防止 redis的key 的重复,我们在前面设置一个前缀,防止重复...
* 两级的控制....
*/
public abstract class BasePrefix implements KeyPrefix{
private int expireSeconds;
private String prefix;
public BasePrefix(String prefix){
this(0,prefix);
}
public BasePrefix(int expireSeconds, String prefix) {
this.expireSeconds = expireSeconds;
this.prefix = prefix;
}
/**
* 0 代表永远不过期
* @return
*/
@Override
public int expireSeconds() {
return expireSeconds;
}
@Override
public String getPrefix() {
String simpleName = getClass().getSimpleName();
StringBuffer sb = new StringBuffer(simpleName);
sb.append(":");
sb.append(prefix);
sb.append(":");
return sb.toString();
}
}
3.RedisService 的封装
@Service
public class RedisService {
@Autowired
private JedisPool jedisPool;
/**
* 获取对象
* @param keyPrefix
* @param key
* @param clazz
* @param <T>
* @return
*/
public <T> T get(KeyPrefix keyPrefix,String key, Class<T> clazz) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//拼接上前缀
String s = jedis.get(keyPrefix.getPrefix()+key);
T t = stringToBean(s,clazz);
return t;
} finally {
returnToPool(jedis);
}
}
/**
* 设置对象
* @param keyPrefix
* @param key
* @param value
* @param <T>
*/
public <T> void set(KeyPrefix keyPrefix,String key, T value) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
String s = beanToString(value);
if (s == null) {
return;
}
//拼接上前缀
int seconds = keyPrefix.expireSeconds();
String realKey = keyPrefix.getPrefix() + key;
if(seconds>0){
jedis.setex(realKey,seconds,s);
}else {
jedis.set(realKey, s);
}
} finally {
returnToPool(jedis);
}
}
/**
* 键是否存在
* @param keyPrefix
* @param key
* @return
*/
public boolean exist(KeyPrefix keyPrefix,String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//拼接上前缀
return jedis.exists(keyPrefix.getPrefix()+key);
} finally {
returnToPool(jedis);
}
}
/**
* delete 方法
* @param keyPrefix
* @param key
* @return
*/
public boolean delete(KeyPrefix keyPrefix,String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//拼接上前缀
Long del = jedis.del(keyPrefix.getPrefix() + key);
return del>1;
} finally {
returnToPool(jedis);
}
}
/**
* +1
* @param keyPrefix
* @param key
* @return
*/
public Long incr(KeyPrefix keyPrefix,String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//拼接上前缀
return jedis.incr(keyPrefix.getPrefix()+key);
} finally {
returnToPool(jedis);
}
}
/**
* -1
* @param keyPrefix
* @param key
* @return
*/
public Long decr(KeyPrefix keyPrefix,String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//拼接上前缀
return jedis.decr(keyPrefix.getPrefix()+key);
} finally {
returnToPool(jedis);
}
}
public static <T> String beanToString(T value) {
if (value == null) {
return null;
}
Class<?> aClass = value.getClass();
if (aClass == int.class || aClass == Integer.class) {
return String.valueOf(value);
} else if (aClass == String.class) {
return String.valueOf(value);
} else if (aClass == long.class || aClass == Long.class) {
return String.valueOf(value);
} else {
return JSON.toJSONString(value);
}
}
public static <T> T stringToBean(String s, Class<T> aClass) {
if(s==null || s.length()<=0){
return null;
}
if (aClass == int.class || aClass == Integer.class) {
return (T)Integer.decode(s);
} else if (aClass == String.class) {
return (T)s;
} else if (aClass == long.class || aClass == Long.class) {
return (T)Long.decode(s);
} else {
return JSON.parseObject(s,aClass);
}
}
/**
* 返回到连接池中去
*
* @param jedis
*/
private void returnToPool(Jedis jedis) {
if (jedis != null) {
jedis.close();
}
}
public boolean delete(KeyPrefix prefix) {
if(prefix == null) {
return false;
}
List<String> keys = scanKeys(prefix.getPrefix());
if(keys==null || keys.size() <= 0) {
return true;
}
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
jedis.del(keys.toArray(new String[0]));
return true;
} catch (final Exception e) {
e.printStackTrace();
return false;
} finally {
if(jedis != null) {
jedis.close();
}
}
}
public List<String> scanKeys(String key) {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
List<String> keys = new ArrayList<String>();
String cursor = "0";
ScanParams sp = new ScanParams();
sp.match("*"+key+"*");
sp.count(100);
do{
ScanResult<String> ret = jedis.scan(cursor, sp);
List<String> result = ret.getResult();
if(result!=null && result.size() > 0){
keys.addAll(result);
}
//再处理cursor
cursor = ret.getStringCursor();
}while(!cursor.equals("0"));
return keys;
} finally {
if (jedis != null) {
jedis.close();
}
}
}
}
4.前缀的封装示例
public class MiaoshaKey extends BasePrefix{
private MiaoshaKey(int expireSeconds, String prefix) {
super(expireSeconds,prefix);
}
public static MiaoshaKey isGoodsOver=new MiaoshaKey(0,"go");
public static MiaoshaKey miaoshaPath=new MiaoshaKey(60,"mp");
public static MiaoshaKey getMiaoshaVerifyCode=new MiaoshaKey(300,"vs");
}
public class OrderKey extends BasePrefix{
private OrderKey(String prefix) {
super(prefix);
}
public static OrderKey getOrderByUserIdGoodsId=new OrderKey("id");
}
为什么没有使用枚举,因为这里涉及到了 key 的有效期,有的是一直有效的,有的有过期时间,所以直接使用class进行更加灵活的封装了.
5.使用示例
public boolean getGoodsOver(long goodsId) {
return redisService.exist(MiaoshaKey.isGoodsOver,goodsId+"");
}
public void setGoodsOver(long goodsId) {
//假设这里的goodsId是1
redisService.set(MiaoshaKey.isGoodsOver,goodsId+"",true);
}
这样设置到的key就是 miaoshaKey:go:1 值是true
这样就能够良好的避免key 的冲突
这个是看了慕课网上的视频,有感,得到的结果.
Java Framework,欢迎各位前来交流java相关
QQ群:965125360
推荐JVM的视频:
深入理解Java虚拟机(jvm性能调优+内存模型+虚拟机原理)
https://item.taobao.com/item.htm?spm=a1z38n.10677092.0.0.c9e51deb8seTn4&id=583526620411