注意:本章代码是在上一章的基础上进行添加修改,上一章链接《第九章 企业项目开发--分布式缓存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的线程安全问题,是如何解决的?

第十章 企业项目开发--分布式缓存Redis(2)的更多相关文章

  1. 企业项目开发--分布式缓存Redis

    第九章 企业项目开发--分布式缓存Redis(1) 注意:本章代码将会建立在上一章的代码基础上,上一章链接<第八章 企业项目开发--分布式缓存memcached> 1.为什么用Redis ...

  2. 第九章 企业项目开发--分布式缓存Redis(1)

    注意:本章代码将会建立在上一章的代码基础上,上一章链接<第八章 企业项目开发--分布式缓存memcached> 1.为什么用Redis 1.1.为什么用分布式缓存(或者说本地缓存存在的问题 ...

  3. 第八章 企业项目开发--分布式缓存memcached

    注意:本节代码基于<第七章 企业项目开发--本地缓存guava cache> 1.本地缓存的问题 本地缓存速度一开始高于分布式缓存,但是随着其缓存数量的增加,所占内存越来越大,系统运行内存 ...

  4. 企业项目开发--分布式缓存memcached(3)

    此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 3.3.ssmm0-data 结构: 3.3.1.pom.xml  1 <?xml version=& ...

  5. 第七章 企业项目开发--本地缓存guava cache

    1.在实际项目开发中,会使用到很多缓存技术,而且数据库的设计一般也会依赖于有缓存的情况下设计. 常用的缓存分两种:本地缓存和分布式缓存. 常用的本地缓存是guava cache,本章主要介绍guava ...

  6. 企业项目开发--本地缓存guava cache(1)

    此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 1.在实际项目开发中,会使用到很多缓存技术,而且数据库的设计一般也会依赖于有缓存的情况下设计. 常用的缓存分 ...

  7. 企业项目开发--本地缓存guava cache(2)

    此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. AdminCacheKey: package com.xxx.vo.userManagement; /** ...

  8. 第十一章 企业项目开发--消息队列activemq

    注意:本章代码基于 第十章 企业项目开发--分布式缓存Redis(2) 代码的github地址:https://github.com/zhaojigang/ssmm0 消息队列是分布式系统中实现RPC ...

  9. 【开源项目系列】如何基于 Spring Cache 实现多级缓存(同时整合本地缓存 Ehcache 和分布式缓存 Redis)

    一.缓存 当系统的并发量上来了,如果我们频繁地去访问数据库,那么会使数据库的压力不断增大,在高峰时甚至可以出现数据库崩溃的现象.所以一般我们会使用缓存来解决这个数据库并发访问问题,用户访问进来,会先从 ...

随机推荐

  1. jenkins 插件,下载地址

    http://updates.jenkins-ci.org/download/plugins/ 通常我们需要下载的插件有如下几个:

  2. jquery zTree异步加载的例子

    下面是使用zTree异步加载的一个例子: 1)初始化树的时候是ajax请求,返回nodes列表来初始化树的:如果一开始就异步的话,$.fn.zTree.init($("#zTree" ...

  3. Nginx 多重条件判断

    server{ listen 80; server_name xxx.com; index index.html index.htm index.php admin.php; root /home/w ...

  4. 原始的生成对抗网络GAN

    论文地址:https://arxiv.org/pdf/1406.2661.pdf 1.简介: GAN的两个模型 判别模型:就是图中右半部分的网络,直观来看就是一个简单的神经网络结构,输入就是一副图像, ...

  5. js插件---在线类似excel生成图表插件解决方案

    js插件---在线类似excel生成图表插件解决方案 一.总结 一句话总结:google比百度好用多了,多用google google js editable table jquery 双向绑定 这种 ...

  6. php正则表达式的三个最基本原则分享

    我个人认为,正则表达式的常规用法可以分为如下三个最基本的原则:1.找谁.2.怎么找.3.找它干什么. 接下来,我分享一下一个正则表达式分三个部分: 原子字符 . 匹配除换行符以外的任意字符 \w 匹配 ...

  7. English trip -- VC(情景课)10 D Reading 阅读练习

    Read 阅读  From: Lupe To:Miriam Hi Miriam, I'm not working today.It's my day off. Are you busy?Come an ...

  8. 20170709pptVBA递归删除LOGO图片与文字

    Public Sub StartRecursionFolder() Dim Pre As Presentation Dim FolderPath As String Dim pp As String ...

  9. android--------ExpandableListView的使用多级列表

    多级列表ExpandableListView 扩展列表能够显示一个指示在每项显示项的当前状态(状态通常是一个扩展的组,组的孩子,或倒塌,最后一个孩子).使用setchildindicator(draw ...

  10. Kali Linux on Android # 实测:小米2s离线安装Kali Linux

    小米2s 离线安装Kali Linux 2017年2月4日  by 小甘丶 前段时间也研究过一两天,没弄明白,今天突然来兴致了,说研究一下吧,结果一不小心,就弄明白了! 第一次研究,主要是没弄明白这个 ...