Redis实战之Jedis使用技巧详解
目录
- 一、摘要
- 二、Jedis
- 2.1、基本使用
- 2.2、连接池
- 2.3、连接池配置
- 2.4、字符串常用 API 操作
- 2.5、哈希常用 API 操作
- 2.6、列表常用 API 操作
- 2.7、集合常用 API 操作
- 2.8、有序集合常用 API 操作
- 三、集群配置
- 3.1、哨兵模式
- 3.2、集群模式
- 四、小结
一、摘要
在上一篇文章中,我们详细的介绍了 Redis 的安装和常见的操作命令,以及可视化工具的介绍。
刚知道服务端的操作知识,还是远远不够的,如果想要真正在项目中得到应用,我们还需要一个 redis 的客户端,然后将其集成到项目中,让程序自动根据我们的业务需要自动处理。
基于 redis 开放的通信协议,大神们纷纷开发了各种语言的 redis 客户端,有 c、c++、Java、python、php、nodejs 等等开发语言的客户端,准确来说其实这些客户端都是基于 redis 命令做了一层封装,然后打包成工具以便大家更佳方便的操作 redis,以 Java 项目为例,使用最广的就是以下三种客户端:
- Jedis
- Lettuce
- Redisson
由于篇幅的原因,我们分三篇文章来详细的讲解每个客户端的使用方式以及它的优缺点。
废话不多说,直奔主题!
二、Jedis
Jedis 是老牌的 Redis 的 Java 客户端,提供了比较全面的 Redis 命令的操作支持,也是目前使用最广泛的客户端。
官方网址如下:
https://github.com/redis/jedis
如何在项目中集成 Jedis 呢?请看下文!
2.1、基本使用
首先创建一个普通的 Maven 项目,然后添加Jedis
依赖包!
<dependency> <grandroidoupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.9.0</version> </dependency>
然后创建一个简单的测试,即可实现连接!
publicclassJedisMain{ publicstaticvoidmain(String[]args){ //1.构造一个Jedis对象,因为这里使用的默认端口6379,所以不用配置端口 Jedisjedis=newJedis("127.0.0.1",6379); //2.密码认证 jedis.auth("111111"); //3.测试是否连接成功 Stringping=jedis.ping(); //4.返回pong表示连接成功 System.out.println(ping); } }
对于 Jedis 而言,一旦连接上了 Redis 服务器,剩下的操作就非常容易了,由于 Jedis 中的 API 和 Redis 的命令高度一致,所以,Jedis 中的方法见名知意,直接使用即可。
2.2、连接池
虽然 redis 服务端是单线程操作,但是在实际项目中,使用 Jedis 对象来操作 redis 时,每次操作都需要新建/关闭 TCP 连接,连接资源开销很高,同时 Jedis 对象的个数不受限制,在极端情况下可能会造成连接泄漏,同时 Jedis 存在多线程不安全的问题。
为什么说 Jedis 线程不安全,更加详细的原因可以参考:
所以我们需要将 Jedis 交给线程池来管理,使用 Jedis 对象时,从连接池获取 Jedis,使用完成之后,再还给连接池。
在使用之前,需要添加common-pool
线程池依赖包!
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>js2.11.1</version> </dependency>
创建一个简单的使用线程池测试用例。
publicclassJedisPoolMain{ publicstaticvoidmain(String[]args){ //1.构造一个Jedis连接池 JedisPoolpool=newJedisPool("127.0.0.1",6379); //2.从连接池中获取一个Jedis连接 Jedisjedis=pool.getResource(); jedis.auth("111111"); //3.Jedis操作 Stringping=jedis.ping(); System.out.println(ping); //4.归还连接 jedis.close(); } }
2.3、连接池配置
在实际的使用过程中,我们常常会这样来初始化线程池JedisPool
,详细代码如下:
publicclassRedisPoolUtils{ privatestaticJedisPooljedisPool=null; /** *redis服务器地址 */ privatestaticStringaddr="127.0.0.1"; /** *redis服务器端口 */ privatestaticintport=6379; /** javascript*redis服务器密码 */ privatestaticStringauth="111111"; static{ try{ JedisPoolConfigconfig=newJedisPoolConfig(); //连接耗尽时是否阻塞,false报异常,ture阻塞直到超时,默认true config.setblockWhenExhausted(true); //设置的逐出策略类名,默认DefaultEvictionPolicy(当连接超过最大空闲时间,或连接数超过最大空闲连接数) config.setEvictionPolicyClassName("org.apache.commons.pool2.impl.DefaultEvictionPolicy"); //是否启用pool的jmx管理功能,默认true config.setJmxEnabled(true); //MBeanObjectName=newObjectName("org.apache.commons.pool2:type=GenericObjectPool,name="+"pool"+i);默认为"pool",JMX不熟,具体不知道是干啥的...默认就好. config.setJmxNamePrefix("pool"); //是否启用后进先出,默认true config.setLifo(true); //最大空闲连接数,默认8个 config.setMaxIdle(8); //最大连接数,默认8个 config.setMaxTotal(8); //获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常,小于零:阻塞不确定的时间,默认-1 config.setMaxWaitMillis(-1); //逐出连接的最小空闲时间默认1800000毫秒(30分钟) config.setMinEvictableIdleTimeMillis(1800000); //最小空闲连接数,默认0 config.setMinIdle(0); //每次逐出检查时逐出的最大数目如果为负数就是:1/abs(n),默认3 config.setNumTestsPerEvictionRun(3); //对象空闲多久后逐出,当空闲时间>该值且空闲连接>最大空闲数时直接逐出,不再根据MinEvictableIdleTimeMillis判断(默认逐出策略) config.setSoftMinEvictableIdleTimeMillis(1800000); //在获取连接的时候检查有效性,默认false config.setTestOnBorrow(false); //在空闲时检查有效性,默认false config.setTestWhileIdle(false); //逐出扫描的时间间隔(毫秒)如果为负数,则不运行逐出线程,默认-1 config.setTimeBetweenEvictionRunsMillis(-1); jedisPool=newJedisPool(config,addr,port,3000,auth); }catch(Exceptione){ e.printStackTrace(); } } /** *获取Jedis资源 *@return */ publicstaticJedisgetJedis(){ if(jedisPool!=null){ returnjedisPool.getResource(); } returnnull; } /** *释放Jedis资源 */ publicstaticvoidclose(finalJedisjedis){ if(jedis!=null){ jedis.close(); } } }
简单测试
publicstaticvoidmain(String[]args)throwsInterruptedException{ //获取jedis客户端 Jedisjedis=RedisPoolUtils.getJedis(); System.out.println("清空数据:"+jedis.flushDB()); System.out.println("判断某个键是否存在:"+jedis.exists("username")); System.out.println("新增<'username','xmr'>的键值对:"+jedis.set("username","xmr")); System.out.println(jedis.exists("username")); System.out.println("新增<'password','password'>的键值对:"+jedis.set("password","123")); System.out.print("系统中所有的键如下:"); Set<String>keys=jedis.keys("*"); System.out.println(keys); System.out.println("删除键password:"+jedis.del("password")); System.out.println("判断键password是否存在:"+jedis.exists("password")); System.out.println("设置键username的过期时间为5s:"+jedis.expire("username",8L)); TimeUnit.SECONDS.sleep(1); System.out.println("查看键username的剩余生存时间:"+jedis.ttl("username")); System.out.println("移除键username的生存时间:"+jedis.persist("username")); System.out.println("查看键username的剩余生存时间:"+jedis.ttl("username")); System.out.println("查看键username所存储的值的类型:"+jedis.type("username")); RedisPoolUtils.close(jedis); }
运行结果如下:
清空数据:OK
判断某个键是否存在:false新增<'username','xmr'>的键值对:OKtrue新增<'password','password'>的键值对:OK系统中所有的键如下:[password, username]删除键password:1判断键password是否存在:false设置键username的过期时间为5s:1查看键username的剩余生存时间:7移除键username的生存时间:1查看键username的剩余生存时间:-1查看键username所存储的值的类型:string
2.4、字符串常用 API 操作
publicclassRedisClientUtil{ privatestaticfinalLoggerlog=LoggerFactory.getLogger(RedisClientUtil.class); /** *获取指定key的值,如果key不存在返回null *返回值:返回key的值,如果key不存在时,返回nil *@paramkey *@return */ publicstaticStringget(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.get(key); }catch(Exceptione){ log.error("get命令操作失败,请求参数:{}",key,e); } returnnull; } /** *设置key的值为value *返回值:操作成功完成时返回OK *@paramkey *@return */ publicstaticStringset(Stringkey,Stringvalue){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.set(key,value); }catch(Exceptione){ log.error("set命令操作失败,参数key:{},参数value:{}",key,value,e); } returnnull; } /** *删除指定的key,返回值:被删除key的数量 *返回值:被删除key的数量 *@paramkey *@return */ publicstaticLongdel(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ Longresult=jedis.del(key); returnjedis.del(key); }catch(Exceptione){ log.error("del命令操作失败,参数key:{}",key,e); } return0L; } /** *通过key向指定的value值追加值 *返回值:追加指定值之后,key中字符串的长度 *@paramkey *@return */ publicstaticLongappend(Stringkey,Stringvalue){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.append(key,value); }catch(Exceptione){ log.error("append命令操作失败,参数key:{},参数value:{}",key,value,e); } return0L; } /** *判断key是否存在 *返回值:true/false *@paramkey *@return */ publicstaticBooleanexists(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.exists(key); }catch(Exceptione){ log.error("exists命令操作失败,参数key:{}",key,e); } returnfalse; } /** *设置key的超时时间为seconds *返回值:若key存在返回1,否则返回0 *@paramkey *@return */ publicstaticLongexpire(Stringkey,longseconds){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.expire(key,seconds); }catch(Exceptione){ log.error("expire命令操作失败,参数key:{},参数seconds:{}",key,seconds,e); } return0L; } /** *返回key的剩余过期时间(单位秒) *返回值:当key不存在时,返回-2。当key存在但没有设置剩余生存时间时,返回-1。否则,以秒为单位,返回key的剩余生存时间 *@paramkey *@return */ publicstaticLongttl(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.ttl(key); }catch(Exceptione){ log.error("ttl命令操作失败,参数key:{}",key,e); } return0L; } /** *设置指定key的值为value,当key不存在时才设置 *返回值:设置成功返回1,设置失败返回0 *@paramkey *@return */ publicstaticLongsetnx(Stringkey,Stringvalue){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.setnx(key,value); }catch(Exceptione){ log.error("setnx命令操作失败,参数key:{},参数value:{}",key,value,e); } return0L; } /** *设置指定key的值为value,并设置过期时间 *返回值:设置成功时返回OK *@paramkey *@return */ publicstaticStringsetex(Stringkey,Stringvalue,longseconds){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.setex(key,seconds,value); }catch(Exceptione){ log.error("setex命令操作失败,参数key:{},参数value:{}",key,value,e); } returnnull; } /** *通过key和offset从指定的位置开始将原先value替换 *返回值:被修改后的字符串长度 *@paramkey *@return */ publicstaticLongsetrange(Stringkey,intoffset,Stringvalue){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.setrange(key,offset,value); }catch(Exceptione){ log.error("setrange命令操作失败,参数key:{},参数value:{},参数offset:{}",key,value,offset,e); } returnnull; } /** *通过批量的key获取批量的value *返回值:一个包含所有给定key的值的列表。 *@paramkeys *@return */ publicstaticList<String>mget(String...keys){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.mget(keys); }catch(Exceptione){ log.error("mget命令操作失败,参数key:{}",keys.toString(),e); } returnnull; } /** *批量的设置key:value,也可以一个 *返回值:总是返回OK *@paramkeysValues *@return */ publicstaticStringmset(String...keysValues){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.mset(keysValues); }catch(Exceptione){ log.error("mset命令操作失败,参数key:{}",keysValues.toString(),e); } returnnull; } /** *设置key的值,并返回一个旧值 *返回值:返回给定key的旧值,当key没有旧值时,即key不存在时,返回nil *@paramkey *@return */ publicstaticStringgetSet(Stringkey,Stringvalue){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.getSet(key,value); }catch(Exceptione){ log.error("getSet命令操作失败,参数key:{},参数value:{}",key,value,e); } returnnull; } /** *通过下标和key获取指定下标位置的value *返回值:截取得到的子字符串 *@paramkey *@return */ publicstaticStringgetrange(Stringkey,intstartOffset,intendOffset){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.getrange(key,startOffset,endOffset); }catch(Exceptione){ log.error("getrange命令操作失败,参数key:{},参数startOffset:{},参数offset:{}",key,startOffset,endOffset,e); } returnnull; } /** *通过key对value进行加值+1操作,当value不是int类型时会返回错误,当key不存在是则value为1 *返回值:执行INCR命令之后key的值 *@paramkey *@return */ publicstaticLongincr(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.incr(key); }catch(Exceptione){ log.error("incr命令操作失败,参数key:{}",key,e); } return0L; } /** *通过key给指定的value加值 *返回值:执行INCR命令之后key的值 *@paramkey *@return */ 开发者_DB2publicstaticLongincrBy(Stringkey,longincrement){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.incrBy(key,increment); }catch(Exceptione){ log.error("incrBy命令操作失败,参数key:{},参数increment:{}",key,increment,e); } return0L; } /** *对key的值做减减操作 *返回值:执行INCR命令之后key的值 *@paramkey *@return */ publicstaticLongdecr(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.decr(key); }catch(Exceptione){ log.error("decr命令操作失败,参数key:{}",key,e); } return0L; } /** *对key的值做减减操作,减去指定的值 *返回值:执行INCR命令之后key的值 *@paramkey *@return */ publicstaticLongdecrBy(Stringkey,longdecrement){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.decrBy(key,decrement); }catch(Exceptione){ log.error("decrBy命令操作失败,参数key:{},参数decrement:{}",key,decrement,e); } return0L; } /** *通过key获取value值的长度 *返回值:value值的长度 *@paramkey *@return */ publicstaticLongstrlen(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.strlen(key); }catch(Exceptione){ log.error("strlen命令操作失败,参数key:{}",key,e); } return0L; } }
2.5、哈希常用 API 操作
publicclassRedisClientUtil{ privatestaticfinalLoggerlog=LoggerFactory.getLogger(RedisClientUtil.class); /** *通过key和field获取指定的value *返回值:对应的value值 *@paramkey *@return */ publicstaticStringhget(Stringkey,Stringfield){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.hget(key,field); }catch(Exceptione){ log.error("hget命令操作失败,参数key:{},参数field:{}",key,f编程ield,e); } returnnull; } /** *通过key给field设置指定的值,如果key不存在,则先创建 *返回值:如果字段是哈希表中的一个新建字段,并且值设置成功,返回1;如果哈希表中域字段已经存在且旧值已被新值覆盖,返回0。 *@paramkey *@return */ publicstaticLonghset(Stringkey,Stringfield,Stringvalue){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.hset(key,field,value); }catch(Exceptione){ log.error("hset命令操作失败,参数key:{},参数field:{},参数value:{}",key,field,value,e); } return0L; } /** *通过key和field判断是否有指定的value存在 *返回值:true/false *@paramkey *@return */ publicstaticBooleanhexists(Stringkey,Stringfield){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.hexists(key,field); }catch(Exceptione){ log.error("hexists命令操作失败,参数key:{},参数field:{}",key,field,e); } returnfalse; } /** *通过key返回field的数量 *返回值:field的数量 *@paramkey *@return */ publicstaticLonghlen(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.hlen(key); }catch(Exceptione){ log.error("hlen命令操作失败,参数key:{}",key,e); } return0L; } /** *通过key删除指定的field *返回值:删除的数量 *@paramkey *@return */ publicstaticLonghdel(Stringkey,String...fields){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.hdel(key,fields); }catch(Exceptione){ log.error("hdel命令操作失败,参数key:{},参数fields:{}",key,fields.toString(),e); } return0L; } /** *通过key返回所有的field *返回值:field集合 *@paramkey *@return */ publicstaticSet<String>hkeys(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.hkeys(key); }catch(Exceptione){ log.error("hkeys命令操作失败,参数key:{}",key,e); } returnnull; } /** *通过key获取所有的field和value *返回值:map对象 *@paramkey *@return */ publicstaticMap<String,String>hgetAll(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.hgetAll(key); }catch(Exceptione){ log.error("hgetAll命令操作失败,参数key:{}",key,e); } returnnull; } }
2.6、列表常用 API 操作
publicclassRedisClientUtil{ privatestaticfinalLoggerlog=LoggerFactory.getLogger(RedisClientUtil.class); /** *过key向list头部添加字符串 *返回值:执行LPUSH命令后,列表的长度 *@paramkey *@return */ publicstaticLonglpush(Stringkey,String...strs){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.lpush(key,strs); }catch(Exceptione){ log.error("lpush命令操作失败,参数key:{},参数strs:{}",key,strs.toString(),e); } returnnull; } /** *通过key向list尾部添加字符串 *返回值:执行RPUSH命令后,列表的长度 *@paramkey *@return */ publicstaticLongrpush(Stringkey,String...strs){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.rpush(key,strs); }catch(Exceptione){ log.error("rpush命令操作失败,参数key:{},参数strs:{}",key,strs.toString(),e); } returnnull; } /** *通过key设置list指定下标位置的value如果下标超过list里面value的个数则报错 *返回值:操作成功返回ok,否则返回错误信息 *@paramkey *@return */ publicstaticStringlset(Stringkey,Longindex,Stringvalue){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.lset(key,index,value); }catch(Exceptione){ log.error("lset命令操作失败,参数key:{},参数index:{},参数value:{}",key,index,value,e); } returnnull; } /** *通过key从对应的list中删除指定的count个和value相同的元素 *返回值:返回被删除的个数 *@paramkey *@return */ publicstaticLonglrem(Stringkey,longcount,Stringvalue){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.lrem(key,count,value); }catch(Exceptione){ log.error("lrem命令操作失败,参数key:{},参数count:{},参数value:{}",key,count,value,e); } returnnull; } /** *通过key保留list中从strat下标开始到end下标结束的value值 *返回值:操作成功返回ok,否则返回错误信息 *@paramkey *@return */ publicstaticStringltrim(Stringkey,longstart,longend){ try(Jedisjedis=jedisPool.getResource()){ returnj编程edis.ltrim(key,start,end); }catch(Exceptione){ log.error("ltrim命令操作失败,参数key:{},参数start:{},参数end:{}",key,start,end,e); } returnnull; } /** *通过key从list的头部删除一个value,并返回该value *返回值:value值 *@paramkey *@return */ publicstaticStringlpop(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.lpop(key); }catch(Exceptione){ log.error("lpop命令操作失败,参数key:{}",key,e); } returnnull; } /** *通过key从list尾部删除一个value,并返回该元素 *返回值:value值 *@paramkey *@return */ publicstaticStringrpop(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.rpop(key); }catch(Exceptione){ log.error("rpop命令操作失败,参数key:{}",key,e); } returnnull; } /** *通过key获取list中指定下标位置的value *返回值:value值 *@paramkey *@return */ publicstaticStringlindex(Stringkey,longindex){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.lindex(key,index); }catch(Exceptione){ log.error("lindex命令操作失败,参数key:{},参数index:{}",key,index,e); } returnnull; } /** *通过key返回list的长度 *返回值:value值 *@paramkey *@return */ publicstaticLongllen(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.llen(key); }catch(Exceptione){ log.error("llen命令操作失败,参数key:{}",key,e); } returnnull; } /** *通过key获取list指定下标位置的value如果start为0end为-1则返回全部的list中的value *返回值:value值 *@paramkey *@return */ publicstaticList<String>lrange(Stringkey,longstart,longend){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.lrange(key,start,end); }catch(Exceptione){ log.error("lrange命令操作失败,参数key:{},参数start:{},参数end:{}",key,start,end,e); } returnnull; } }
2.7、集合常用 API 操作
publicclassRedisClientUtil{ privatestaticfinalLoggerlog=LoggerFactory.getLogger(RedisClientUtil.class); /** *通过key向指定的set中添加value *返回值:添加成功的个数 *@paramkey *@return */ publicstaticLongsadd(Stringkey,String...members){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.sadd(key,members); }catch(Exceptione){ log.error("sadd命令操作失败,参数key:{},参数members:{}",key,members.toString(),e); } returnnull; } /** *通过key删除set中对应的value值 *返回值:删除成功的个数 *@paramkey *@return */ publicstaticLongsrem(Stringkey,String...members){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.srem(key,members); }catch(Exceptione){ log.error("srem命令操作失败,参数key:{},参数members:{}",key,members.toString(),e); } returnnull; } /** *通过key获取set中value的个数 *返回值:value的个数 *@paramkey *@return */ publicstaticLongscard(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.scard(key); }catch(Exceptione){ log.error("scard命令操作失败,参数key:{}",key,e); } return0L; } /** *通过key判断value是否是set中的元素 *返回值:true/false *@paramkey *@return */ publicstaticBooleansismember(Stringkey,Stringmember){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.sismember(key,member); }catch(Exceptione){ log.error("sismember命令操作失败,参数key:{},参数member:{}",key,member,e); } returnfalse; } /** *通过key获取set中所有的value *返回值:所有的value *@paramkey *@return */ publicstaticSet<String>smembers(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.smembers(key); }catch(Exceptione){ log.error("smembers命令操作失败,参数key:{}",key,e); } returnnull; } }
2.8、有序集合常用 API 操作
publicclassRedisClientUtil{ privatestaticfinalLoggerlog=LoggerFactory.getLogger(RedisClientUtil.class); /** *通过key向zset中添加value,score,其中score就是用来排序的如果该value已经存在则根据score更新元素 *返回值:被成功添加的新成员的数量,不包括那些被更新的、已经存在的成员 *@paramkey *@return */ publicstaticLongzadd(Stringkey,doublescore,Stringmember){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.zadd(key,score,member); }catch(Exceptione){ log.error("zadd命令操作失败,参数key:{},参数score:{},参数member:{}",key,score,member,e); } returnnull; } /** *通过key删除在zset中指定的value *返回值:删除个数 *@paramkey *@return */ publicstaticLongzrem(Stringkey,String...members){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.zrem(key,members); }catch(Exceptione){ log.error("zrem命令操作失败,参数key:{},参数members:{}",key,members.toString(),e); } returnnull; } /** *通过key增加该zset中value的score的值 *返回值:member成员的新分数值 *@paramkey *@return */ publicstaticDoublezincrby(Stringkey,doublescore,Stringmember){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.zincrby(key,score,member); }catch(Exceptione){ log.error("zincrby命令操作失败,参数key:{},参数score:{},参数member:{}",key,score,member,e); } returnnull; } /** *通过key返回zset中value的排名下标从小到大排序 *返回值:返回member的排名 *@paramkey *@return */ publicstaticLongzrank(Stringkey,Stringmember){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.zrank(key,member); }catch(Exceptione){ log.error("zrank命令操作失败,参数key:{},参数member:{}",key,member,e); } returnnull; } /** *通过key将获取score从start到end中zset的valuesocre从大到小排序当start为0end为-1时返回全部 *返回值:返回member集合 *@paramkey *@return */ publicstaticSet<String>zrevrange(Stringkey,longstart,longend){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.zrevrange(key,start,end); }catch(Exceptione){ log.error("zrevrange命令操作失败,参数key:{},参数start:{},参数end:{}",key,start,end,e); } returnnull; } /** *返回指定区间内zset中value的数量 *返回值:返回member集合 *@paramkey *@return */ publicstaticLongzcount(Stringkey,Stringmin,Stringmax){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.zcount(key,min,max); }catch(Exceptione){ log.error("zcount命令操作失败,参数key:{},参数min:{},参数max:{}",key,min,max,e); } returnnull; } /** *通过key返回zset中的value个数 *返回值:返回member集合 *@paramkey *@return */ publicstaticLongzcard(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.zcard(key); }catch(Exceptione){ log.error("zcard命令操作失败,参数key:{}",key,e); } returnnull; } /** *返回满足pattern表达式的所有keykeys(*)返回所有的key *返回值:返回key集合 *@parampattern *@return */ publicstaticSet<String>keys(Stringpattern){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.keys(pattern); }catch(Exceptione){ log.error("keys命令操作失败,参数pattern:{}",pattern,e); } returnnull; } /** *通过key判断值得类型 *返回值:值的类型 *@paramkey *@return */ publicstaticStringtype(Stringkey){ try(Jedisjedis=jedisPool.getResource()){ returnjedis.type(key); }catch(Exceptione){ log.error("type命令操作失败,参数key:{}",key,e); } returnnull; } }
三、集群配置
在实际的项目生产环境中,redis 通常不是以单台服务实例来运行的,因为一旦服务器挂了,可能所有的下游服务都会受到影响,因此为了保障单台服务器即使出现故障也能运行,通常运维组会搭建集群环境,来保证服务高可用。
搭建的方式有两种,哨兵模式和 Cluster 模式。
- 哨兵模式:对redis服务器进行监控,如果有宕机的,就从备机里面选一个出来作为主机,实现自动切换
- Cluster 模式:将数据进行分片存储,避免全部节点数据都一样,浪费空间
3.1、哨兵模式
哨兵模式简单的说,就是一台主机,一台备机,外加一台监控服务,当监控服务观测到主机已经宕机,就会将备用机切换成主机,以便继续提供服务。
publicclassRedisPoolUtils{ privatestaticJedisjedis; privatestaticJedisSentinelPooljedisSentinelPool; static{ try{ JedisPoolConfigconfig=newJedisPoolConfig(); //最大空闲连接数,默认8个 config.setMaxIdle(8); //最大连接数,默认8个 config.setMaxTotal(8); //最小空闲连接数,默认0 config.setMinIdle(0); //获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常,小于零:阻塞不确定的时间,默认-1 config.setMaxWaitMillis(3000); //在获取连接的时候检查有效性,表示取出的redis对象可用,默认false config.setTestOnBorrow(true); //redis服务器列表 Set<String>sentinels=newHashSet<>(); sentinels.add(newHostAndPort("192.168.43.212",26379).toString()); sentinels.add(newHostAndPort("192.168.43.213",26379).toString()); sentinels.add(newHostAndPort("192.168.43.214",26379).toString()); //初始化连接池 jedisSentinelPool=newJedisSentinelPool("mymaster",sentinels,config,"111111"); //从池中获取一个Jedis对象 jedis=jedisSentinelPool.getResource(); }catch(Exceptione){ e.printStackTrace(); } } }
3.2、集群模式
为了保证高可用,redis-cluster集群通常会引入主从复制模型,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点。
publicclassRedisPoolUtils{ static{ try{ JedisPoolConfigconfig=newJedisPoolConfig(); //最大空闲连接数,默认8个 config.setMaxIdle(8); //最大连接数,默认8个 config.setMaxTotal(8); //最小空闲连接数,默认0 config.setMinIdle(0); //获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常,小于零:阻塞不确定的时间,默认-1 config.setMaxWaitMillis(3000); //在获取连接的时候检查有效性,表示取出的redis对象可用,默认false config.setTestOnBorrow(true); Set<HostAndPort>nodes=newHashSet<>(); nodes.add(newHostAndPort("192.168.43.212",26379)); nodes.add(newHostAndPort("192.168.43.213",26379)); nodes.add(newHostAndPort("192.168.43.214",26379)); JedisClusterjedisCluster=newJedisCluster(nodes,config); jedisCluster.set("key","helloworld"); jedisCluster.close(); }catch(Exceptione){ e.printStackTrace(); } } }
四、小结
jedis
客户端是目前使用最广泛的一款 java 客户端,也是老牌的 Redis 的 Java 实现客户端。
优点很突出:
- 比较全面的提供了 Redis 的操作特性,也就是说你能用 redis 命令操作的,Jedis 包都也给你封装好了,直接使用即可
- 使用广泛,易上手
当然,缺点也有:
- Jedis 客户端实例不是线程安全的,需要借助连接池来管理和使用 Jedis
- 使用阻塞的I/O,且其方法调用都是同步的,程序流需要等到 sockets 处理完 I/O 才能执行,不支持异步
到此这篇关于Redis实战之Jedis使用技巧详解的文章就介绍到这了,更多相关Redis Jedis内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
精彩评论