注意:本章代码是在上一章的基础上进行添加修改,上一章链接《第九章 企业项目开发--分布式缓存Redis(1)》
上一章说了ShardedJedisPool的创建过程,以及redis五种数据结构的第一种String类型的常用缓存操作方法。下面说余下的四种:
- list(有序列表)
- set(无序集合)
- sorted set(有序集合)
- hash
1、ssmm0-cache
1.1、RedisListUtil(有序列表工具类)
package com.xxx.cache.redis; import java.util.List; import redis.clients.jedis.ShardedJedis; /**
* list缓存操作类
* 1、顺序为插入list的顺序
* 2、允许存放重复元素
* 3、可用作模拟队列(queue)、堆栈(stack),支持双向操作(L--首部或者R--尾部)
* 4、index从0开始 -1表示结尾 -2表示倒数第二个
* 5、API中的 start end参数 都是包前也包后的
*/
public class RedisListUtil extends RedisBaseUtil{ /***************************添加缓存*****************************/
/**
* 从左边(首部)加入列表
* 注意:
* 1、可以一次性入队n个元素(这里使用了不定参数,当然可以换做数组)
* 2、不定参数必须放在所有参数的最后边
* 3、左边入队,相当于在队头插入元素,则之后的元素都要后移一位;而右边入队的话元素直接插在队尾,之前的元素的索引不变
* 4、没有从list中获取指定value的运算
*/
public static void lpush(String list, String... values){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
/*
* lpush(String key, String... strings);
* 返回push之后的list中包含的元素个数
*/
jedis.lpush(list, values);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /**
* 从左边(首部)加入列表
* 并指定列表缓存过期时间
*/
public static void lpush(String list, int expire, String... values){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
/*
* lpush(String key, String... strings);
* 返回push之后的list中包含的元素个数
*/
jedis.lpush(list, values);
jedis.expire(list, expire);//为该list设置缓存过期时间
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /**
* 从右边(尾部)加入列表
*/
public static void rpush(String list, String... values){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
jedis.rpush(list, values);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /**
* 从右边(尾部)加入列表
* 并设置缓存过期时间
*/
public static void rpush(String list, int expire, String... values){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
jedis.rpush(list, values);
jedis.expire(list, expire);//设置缓存过期时间
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /**
* 设置list中index位置的元素
* index==-1表示最后一个元素
*/
public static void lSetIndex(String list, long index, String value){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
jedis.lset(list, index, value);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /***************************获取缓存*****************************/
/**
* 从左边(首部)出列表
*/
public static String lpop(String list){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return null;
}
return jedis.lpop(list);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return null;
} /**
* 从右边出列表
*/
public static String rpop(String list){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return null;
}
return jedis.rpop(list);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return null;
} /**
* 返回list中index位置的元素
*/
public static String lGetIndex(String list, long index){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return null;
}
return jedis.lindex(list, index);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return null;
} /**
* 返回list指定区间[start,end]内的元素
*/
public static List<String> lrange(String list, long start, long end){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return null;
}
return jedis.lrange(list, start, end);//
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return null;
} /**
* 返回list内的全部元素
*/
public static List<String> lrange(String list){
return lrange(list, 0, -1);
} /*** 删除缓存(删除整个list,直接用RedisStringUtil的delete就好)******/
/**
* 让list只保留指定区间[start,end]内的元素,不在指定区间内的元素都将被删除
*/
public static void ltrim(String list, long start, long end){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
jedis.ltrim(list, start, end);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /**
* 删除list中所有与value相等的元素
* 注意:
* count
* ==0 :删除表中所有与value相等的元素
* >0:从表头开始向表尾搜索,移除count个与value相等的元素
* <0:从表尾开始向表头搜索,移除count个与value相等的元素
*/
public static void lremove(String list, long count, String value){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
jedis.lrem(list, count, value);//返回删除了多少个元素
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /**
* 删除list中所有与value相等的元素
*/
public static void lremove(String list, String value){
lremove(list, 0, value);
} /***************************其他*****************************/
/**
* 返回list*有多少个元素
*/
public static long llength(String list){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return 0;
}
return jedis.llen(list);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return 0;
} public static void main(String[] args) {
lpush("adminList", "jigang");
lpush("adminList", "nana");//头部
System.out.println(llength("adminList"));
System.out.println(lrange("adminList"));
//lpop("adminList");
//System.out.println(llength("adminList"));
//ltrim("adminList", 0, 1);
//System.out.println(lrange("adminList"));
//System.out.println(lpop("adminList"));//左边进左边出,栈(后进先出)
//System.out.println(rpop("adminList"));//左边进右边出,队列(先进先出)
System.out.println(lGetIndex("adminList",1)); }
}
注意:
- 元素在list中的存放顺序为:插入list的顺序(从左边插入在头部,从右边插入在尾部)
- 允许存放重复元素
- 可用作模拟队列(queue)、堆栈(stack),支持双向操作(L--首部或者R--尾部)
- index从0开始 -1表示结尾 -2表示倒数第二个
- API中的 start end参数 都是包前也包后的
- 左边入队,相当于在队头插入元素,则之后的元素都要后移一位;而右边入队的话元素直接插在队尾,之前的元素的索引不变(推荐使用右边入队,即队尾入队)
- 没有从list中获取指定value的运算(这也是set/sorted set所没有的)
- 没有直接的指定缓存过期的API(这也是set/sorted set/hash所没有的),但是可以按例如如下的方式指定缓存过期时间
/**
* 从左边(首部)加入列表
* 并指定列表缓存过期时间
*/
public static void lpush(String list, int expire, String... values){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
/*
* lpush(String key, String... strings);
* 返回push之后的list中包含的元素个数
*/
jedis.lpush(list, values);
jedis.expire(list, expire);//为该list设置缓存过期时间
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} - 删除整个list可以直接使用jedis.del(list)(set/sorted set/hash同理)
1.2、RedisSetUtil(无序集合工具类)
package com.xxx.cache.redis; import java.util.Set; import redis.clients.jedis.ShardedJedis; /**
* set缓存操作类
* 1、无序集合,最后的顺序不一定是插入顺序
* 2、元素不能重复
* 3、对于set而言,Jedis有交集、差集、并集运算,可是ShardJedis没有
* 4、没有从set中获取指定value的运算
*/
public class RedisSetUtil extends RedisBaseUtil {
/***************************添加缓存*****************************/
/**
* 添加缓存
* @param set 缓存将要添加到的set集合
* @param values 添加的缓存元素
*/
public static void sadd(String set, String... values){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
/*
* 对比:
* lpush(String key, String... strings);
* 返回push之后的list中包含的元素个数
*
* sadd(String key, String... members)
* 1:添加元素成功
* 0:set中已经有要添加的元素了
*/
jedis.sadd(set, values);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /***************************获取缓存*****************************/
/**
* 获取set集合中的所有缓存
* @param set
*/
public static Set<String> smembers(String set){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return null;
}
return jedis.smembers(set);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return null;
} /***************************删除缓存*****************************/
/**
* 删除缓存
* @param set
* @param values
*/
public static void sremove(String set, String... values){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
jedis.srem(set, values);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /***************************其他*****************************/
/**
* set集合是否包含value
* @param set
*/
public static boolean sismembers(String set, String value){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return false;
}
return jedis.sismember(set, value);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return false;
} /**
* 返回set集合的元素个数
* @param set
*/
public static long ssize(String set){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return 0;
}
return jedis.scard(set);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return 0;
} /**
* 测试
*/
public static void main(String[] args) {
sadd("adminset", "nana","jigang");
sadd("adminset", "nana2");
System.out.println(smembers("adminset"));
System.out.println(ssize("adminset"));
System.out.println(sismembers("adminset", "jigang"));
sremove("adminset", "jigang");
System.out.println(sismembers("adminset", "jigang"));
} }
注意:
- 元素在set中的存放顺序为:与插入set的先后书顺序无关(即无序)
- 不允许存放重复元素
- 对于set而言,Jedis有交集、差集、并集运算,可是ShardJedis没有
1.3、RedisSortedSet(有序集合工具类)
package com.xxx.cache.redis; import java.util.Map;
import java.util.Set; import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.Tuple; /**
* sorted set缓存操作类
* 1、有序集合,最后的顺序是按照score从小到大的顺序排列
* 2、元素不能重复
* 3、没有从set中获取指定value的运算
*/
public class RedisSortedSetUtil extends RedisBaseUtil {
/***************************添加缓存*****************************/
/**
* 添加缓存(一个)
* @param sortedSet 添加入的集合
* @param score 权重
* @param value 值
*/
public static void zadd(String sortedSet,double score, String value){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
jedis.zadd(sortedSet, score, value);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /**
* 添加缓存(一次可添加多个)
* @param sortedSet 添加入的集合
* @param value2score 加入集合的元素集
*/
public static void zadd(String sortedSet,Map<String, Double> value2score){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
jedis.zadd(sortedSet, value2score);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /***************************获取缓存*****************************/
/**
* 返回sortedSet内[start,end]索引的元素set
* 1、在sortedSet中,元素是按照score从小到大排列的,
* 此方法从前向后获取元素(即按元素的score从小到大排列)
* @param sortedSet
* @param start
* @param end
*/
public static Set<String> zrange(String sortedSet, long start, long end){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return null;
}
return jedis.zrange(sortedSet, start, end);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return null;
} /**
* 返回sortedSet内所有元素,元素按照score从小到大排列
*/
public static Set<String> zrange(String sortedSet){
return zrange(sortedSet, 0, -1);
} /**
* 返回sortedSet集合[start, end]中的元素
* 1、此方法相当于从后向前取元素,即元素从大到小排列
* 或者相当于将sortedSet从大到小排列,然后从前向后去元素
* @param sortedSet
* @param start
* @param end
* @return
*/
public static Set<String> zrevrange(String sortedSet, long start, long end){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return null;
}
return jedis.zrevrange(sortedSet, start, end);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return null;
} /**
* 返回sortedSet内所有元素,元素按照score从大到小排列
*/
public static Set<String> zrevrange(String sortedSet){
return zrevrange(sortedSet, 0, -1);
} /**
* 获取sortedSet内[minScore, maxScore]的元素
* @param sortedSet
* @param minScore
* @param maxScore
* @return
*/
public static Set<String> zrangeByScore(String sortedSet, double minScore, double maxScore){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return null;
}
return jedis.zrangeByScore(sortedSet, minScore, maxScore);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return null;
} /**
* 获取Set<Tuple>集合,其中Tuple是value与score的结构体
* @param sortedSet
* @param minScore
* @param maxScore
* @return
*/
public static Set<Tuple> zrevrangeByScoreWithScores(String sortedSet, double minScore, double maxScore){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return null;
}
return jedis.zrevrangeByScoreWithScores(sortedSet, maxScore, minScore);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return null;
} /***************************删除缓存*****************************/
/**
* 删除多个缓存
* @param sortedSet
* @param values
*/
public static void zremove(String sortedSet, String... values){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
jedis.zrem(sortedSet, values);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /**
* 删除指定范围(按照索引,包前包后)的缓存
* @param sortedSet
* @param start
* @param end
*/
public static void zremrangeByRank(String sortedSet, long start, long end){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
jedis.zremrangeByRank(sortedSet, start, end);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /**
* 删除指定范围(按照分数,包前包后)的缓存
* @param sortedSet
* @param minScore
* @param maxScore
*/
public static void zremrangeByScore(String sortedSet, double minScore, double maxScore){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
jedis.zremrangeByScore(sortedSet, minScore, maxScore);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /***************************其他*****************************/
/**
* 获取集合sortedSet的长度
* @param sortedSet
* @return
*/
public static long zlength(String sortedSet){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return 0;
}
return jedis.zcard(sortedSet);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return 0;
} /**
* 获取sortedSet中的value的权重score
* @param sortedSet
* @param value
* @return
*/
public static double zscore(String sortedSet, String value){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return 0;
}
return jedis.zscore(sortedSet, value);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return 0;
} /**
* 为sortedSet中的value的权重加上增量score
* @param sortedSet
* @param score
* @param value
*/
public static void zincrby(String sortedSet,double score, String value){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
jedis.zincrby(sortedSet, score, value);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /**
* 测试
*/
public static void main(String[] args) {
zadd("aaset", 1, "aa");
zadd("aaset", 4, "bb");
zadd("aaset", 0, "cc"); System.out.println(zrange("aaset", 0, -1));//[cc, aa, bb]
System.out.println(zrange("aaset", 0, 1));//[cc, aa]
System.out.println(zrevrange("aaset", 0, -1));//[bb, aa, cc]
System.out.println(zrevrange("aaset", 0, 1));//[bb, aa]
System.out.println(zrangeByScore("aaset", 0, 2));//[cc, aa]
Set<Tuple> s = zrevrangeByScoreWithScores("aaset", 0, 2);
for(Tuple t : s){
System.out.println(t.getElement()+"-->"+t.getScore());//aa-->1.0 cc-->0.0
} System.out.println(zlength("aaset"));//
System.out.println(zscore("aaset","bb"));//4.0
zincrby("aaset",10,"bb");
System.out.println(zscore("aaset","bb"));//14.0
zremove("aaset", "cc");
System.out.println(zrange("aaset"));//[aa, bb]
zremrangeByScore("aaset", 10, 20);
System.out.println(zrange("aaset"));//[aa]
} }
注意:
- 元素在set中的存放顺序为:根据score(权重)从小到大排列
- 不允许存放重复元素
1.4、RedisHashUtil(hash工具类)
package com.xxx.cache.redis; import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set; import redis.clients.jedis.ShardedJedis; /**
* hash缓存操作类
*/
public class RedisHashUtil extends RedisBaseUtil {
/***************************添加缓存*****************************/
/**
* 添加单个缓存key-value到map中
*/
public static void hset(String map, String key, String value){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
jedis.hset(map, key, value);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /**
* 添加单个缓存key-value到map中
* 若已经存在于指定key相同的key,那么就不操作
*/
public static void hsetnx(String map, String key, String value){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
jedis.hsetnx(map, key, value);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /**
* 在map中添加key2value的map,即一次性添加多条缓存
* @param map
* @param key2value
*/
public static void hmset(String map, Map<String, String> key2value){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
jedis.hmset(map, key2value);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /***************************获取缓存*****************************/
/**
* 获取map中key的集合
* @param set
*/
public static Set<String> hkeys(String map){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return null;
}
return jedis.hkeys(map);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return null;
} /**
* 获取map中的所有key的value
*/
public static List<String> hvals(String map){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return null;
}
return jedis.hvals(map);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return null;
} /**
* 从map中获取多个key的value,并放在List集合中
*/
public static List<String> hmget(String map, String... keys){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return null;
}
return jedis.hmget(map, keys);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return null;
} /**
* 从map中获取全部的缓存key-value对
*/
public static Map<String, String> hgetAll(String map){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return null;
}
return jedis.hgetAll(map);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return null;
} /**
* 从map中获取相应key的缓存value
*/
public static String hget(String map, String key){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return null;
}
return jedis.hget(map, key);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return null;
} /***************************删除缓存*****************************/
/**
* 从map中删除多个缓存
*/
public static void hdel(String map, String... keys){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
jedis.hdel(map, keys);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
} /***************************其他*****************************/
/**
* 获取map中的key-value数
*/
public static long hlen(String map){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return 0;
}
return jedis.hlen(map);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return 0;
} /**
* map中是否存在键为key的缓存
*/
public static boolean hexists(String map, String key){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return false;
}
return jedis.hexists(map, key);
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
return false;
} /**
* 测试
*/
public static void main(String[] args) {
hset("aamap", "aa1", "aa11");
Map<String,String> maps = new HashMap<String, String>();
maps.put("aa2", "aa22");
maps.put("aa3", "aa33");
hmset("aamap", maps); System.out.println(hkeys("aamap"));//[aa3, aa2, aa1]
System.out.println(hvals("aamap"));//[aa33, aa22, aa11]
System.out.println(hgetAll("aamap"));//{aa3=aa33, aa2=aa22, aa1=aa11}
System.out.println(hget("aamap","aa2"));//aa22
System.out.println(hmget("aamap","aa2","aa1"));//[aa22, aa11] System.out.println(hlen("aamap"));//
System.out.println(hexists("aamap","aa3"));//true
System.out.println(hexists("aamap","aa0"));//false hdel("aamap","aa0");
hdel("aamap","aa1");
System.out.println(hgetAll("aamap"));//{aa3=aa33, aa2=aa22} }
}
注意:
- 有根据key获取缓存value的方法
1.5、RedisCacheConstant(创建一些redis使用的自定义的map/set/list/soretd set名)
package com.xxx.cache.util; /**
* 创建一些redis使用的自定义的map/set/list/soretd set名
*/
public enum RedisCacheConstant {
USER_MANAGEMENT_MAP, //人员管理业务类缓存map
HOTEL_MANAGEMENT_MAP; //酒店管理业务类缓存map
}
注意:
- 这一块儿与业务有关
- 在我们的API的设计过程中,可以直接将自己封装的方法中的list/set/sorted set/map参数的类型有String改为RedisCacheConstant,而在方法内部你调用ShardJedis的API的时候,使用String.valueOf(RedisCacheConstant)这样的方式,这样就会减少在实际开发中的代码量。
2、ssmm0-data
AdminService:
/*********************redis hash********************/
/*
* 此处用set、list、sorted set都不太好,因为三者都不具备根据key查找值的能力,
* 以set为例,你缓存的时候,只能缓存一个id进去,最后查询缓存,查到缓存中有ID之后,还需要再根据此ID查询数据库,才能返回具体的admin,还不如直接根据ID去数据库查询
*
* set的一个典型应用场景:
* 当有用户注册或者用户信息修改或用户被删除之后,我们将其ID放入缓存,
* 之后可能会启动一个定时任务,定时扫描该set中是否有ID存在,如果有,说明有用户信息发生变化,
* 然后再进行一些操作,操作之后将set清空。之后继续循环上述的方式
*
* 这里有个问题?set的操作是线程安全的吗?
*/
public Admin findAdminByIdFromRedisHash(int id) {
//从缓存中获取数据:注意这里可以直接将RedisHashUtil中的hget方法的map改为RedisCacheConstant类型,下边同理,其他set、list、sorted set也同理
String adminStr = RedisHashUtil.hget(String.valueOf(RedisCacheConstant.USER_MANAGEMENT_MAP), String.valueOf(id));
//若缓存中有,直接返回
if(StringUtils.isNoneBlank(adminStr)){
return Admin.parseJsonToAdmin(adminStr);
}
//若缓存中没有,从数据库查询
Admin admin = adminDao.getUserById(id);
//若查询出的数据不为null
if(admin!=null){
//将数据存入缓存
RedisHashUtil.hset(String.valueOf(RedisCacheConstant.USER_MANAGEMENT_MAP), String.valueOf(id), admin.toJson());
}
//返回从数据库查询的admin(当然也可能数据库中也没有,就是null)
return admin;
}
说明:在AdminService类中只添加了如上方法。
注意:
- String、hash具有按key查找value的功能
- list、set、sorted set没有按key查找的功能
适用场景:
- 需要按key查找value的,用hash和String
- set类的两种典型应用场景:(归结为一句话:存储特殊的key,之后可能还需要根据这些key进行数据库的查询)
- 当有用户注册或者用户信息修改或用户被删除之后,我们将其ID放入缓存,之后可能会启动一个定时任务,定时扫描该set中是否有ID存在,如果有,说明有用户信息发生变化,然后再进行一些操作,操作之后将set清空。之后继续循环上述的方式
- 存储一个网站的活跃的用户ID,之后我们可以确定set中存在的所有ID都是活跃用户,之后可以按照他们的ID进行数据库的查询;如果用MySQL去做这个事儿,可能需要扫描全表,然后再进行一些操作
3、ssmm0-userManagement
AdminController:
/**
* 根据id查找Admin
*/
@ResponseBody
@RequestMapping("/findAdminByIdFromRedisHash")
public Admin findAdminByIdFromRedisHash(@RequestParam(value="id") int id){ return adminService.findAdminByIdFromRedisHash(id);
}
说明:AdminController中只添加了如上方法。
4、测试
测试方法同上一章。
总结:
- list
- 元素在list中的存放顺序为:插入list的顺序(从左边插入在头部,从右边插入在尾部)
- 允许存放重复元素
- 可用作模拟队列(queue)、堆栈(stack),支持双向操作(L--首部或者R--尾部)
- 左边入队,相当于在队头插入元素,则之后的元素都要后移一位;而右边入队的话元素直接插在队尾,之前的元素的索引不变(推荐使用右边入队,即队尾入队)
- set
- 元素在set中的存放顺序为:与插入set的先后书顺序无关(即无序)
- 不允许存放重复元素
- 对于set而言,Jedis有交集、差集、并集运算,可是ShardJedis没有
- soretd set
- 元素在set中的存放顺序为:根据score(权重)从小到大排列
- 不允许存放重复元素
相同点:
- index
- 从0开始 -1表示结尾 -2表示倒数第二个
- API中的 start end参数
- 都是包前也包后的
- 按key查找功能
- list、set、sorted set没有按key查找的功能
- String、hash具有按key查找value的功能
- 直接的指定缓存过期的API
- String有
- list、set、sorted set、hash没有,但是可以按例如如下的方式指定缓存过期时间
/**
* 从左边(首部)加入列表
* 并指定列表缓存过期时间
*/
public static void lpush(String list, int expire, String... values){
boolean broken = false;//标记:该操作是否被异常打断而没有正常结束
ShardedJedis jedis = null;
try {
jedis = getJedis();//获取jedis实例
if(jedis==null){
broken = true;
return;
}
/*
* lpush(String key, String... strings);
* 返回push之后的list中包含的元素个数
*/
jedis.lpush(list, values);
jedis.expire(list, expire);//为该list设置缓存过期时间
} catch (Exception e) {
broken = true;
}finally{
returnJedis(jedis, broken);
}
}
- 删除整个元素
- jedis.del(list):可用于五种结构
疑问:关于jedis、xmemcached的线程安全问题,是如何解决的?