jedis使用指南.docx

上传人:b****4 文档编号:4344783 上传时间:2022-11-30 格式:DOCX 页数:10 大小:20.46KB
下载 相关 举报
jedis使用指南.docx_第1页
第1页 / 共10页
jedis使用指南.docx_第2页
第2页 / 共10页
jedis使用指南.docx_第3页
第3页 / 共10页
jedis使用指南.docx_第4页
第4页 / 共10页
jedis使用指南.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

jedis使用指南.docx

《jedis使用指南.docx》由会员分享,可在线阅读,更多相关《jedis使用指南.docx(10页珍藏版)》请在冰豆网上搜索。

jedis使用指南.docx

jedis使用指南

jedis使用指南

概述

本文基于jedis-2.1.0和commons-pool-1.5.5。

本文首先会剖析jedis对redis的支持,透过jedis群集之后,那些redis的能力会受到限制,因此第一个部分会重点介绍jedis的关键特性。

对象池的配置会决定jedis的最终性能,而jedis的对象池的实现是基于apache的commons-pool。

本文会重点介绍commons-pool的配置能力,以便为jedis群集提供更好的配置参数。

另外,jedis还有一些扩展包,可以在特定场景下增强jedis的能力,使我们面对特定的应用场景的时候,会有更好的选择。

所以,文档的最后会涉及如何使用jedis的扩展包。

jedis的关键特性

主要是API支持范围,pipeline和transaction的使用,以及对pub/sub的支持。

最后,介绍jedis的客户端群集:

ShardedJedis。

完整的redisAPI支持

jedis首先是redis的java客户端,jedis提供了完整的redis的javaAPI,可以支持完整的redis客户端API。

例如,通过jedis,可以设置redis的主从关系:

jedis.slaveOf("localhost",6379);//ifthemasterisonthesamePCwhichrunsyourcode

jedis.slaveOf("192.168.1.35",6379);

使用pipeline

如果希望一次发送一批redis命令,一种有效的方式是使用pipeline。

jedis使用pipeline的代码如下:

Pipelinep=jedis.pipelined();

p.set("fool","bar");

p.zadd("foo",1,"barowitch");p.zadd("foo",0,"barinsky");p.zadd("foo",0,"barikoviev");

ResponsepipeString=p.get("fool");

Response>sose=p.zrange("foo",0,-1);

p.sync();

intsoseSize=sose.get().size();

SetsetBack=sose.get();

使用transaction

如果希望一些命令一起执行而不被干扰,可以通过transaction将命令打包到一起执行:

jedis.watch(key1,key2,...);

BinaryTransactiont=jedis.multi();

t.set("foo","bar");

t.exec();

如果需要得到返回值,可以参考下面的代码:

Transactiont=jedis.multi();

t.set("fool","bar");

Responseresult1=t.get("fool");

t.zadd("foo",1,"barowitch");t.zadd("foo",0,"barinsky");t.zadd("foo",0,"barikoviev");

Response>sose=t.zrange("foo",0,-1);//gettheentiresortedset

t.exec();//dontforgetit

Stringfoolbar=result1.get();//useResponse.get()toretrievethingsfromaResponse

intsoseSize=sose.get().size();//onsose.get()youcandirectlycallSetmethods!

Publish/Subscribe

如果需要订阅redis的channel,可以创建一个JedisPubSub的派生类的实例,并在jedis上调用其subscribe方法:

classMyListenerextendsJedisPubSub{

publicvoidonMessage(Stringchannel,Stringmessage){

}

publicvoidonSubscribe(Stringchannel,intsubscribedChannels){

}

publicvoidonUnsubscribe(Stringchannel,intsubscribedChannels){

}

publicvoidonPSubscribe(Stringpattern,intsubscribedChannels){

}

publicvoidonPUnsubscribe(Stringpattern,intsubscribedChannels){

}

publicvoidonPMessage(Stringpattern,Stringchannel,

Stringmessage){

}

}

MyListenerl=newMyListener();

jedis.subscribe(l,"foo");

subscribe是一个阻塞的操作。

一个JedisPubSub的实例可以订阅多个redis的channel。

ShardedJedis

简单的说,ShardedJedis是一种帮助提高读/写并发能力的群集,群集使用一致性hash来确保一个key始终被指向相同的redisserver。

每个redisserver被称为一个shard。

因为每个shard都是一个master,因此使用sharding机制会产生一些限制:

不能在sharding中直接使用jedis的transactions、pipelining、pub/sub这些API,基本的原则是不能跨越shard。

但jedis并没有在API的层面上禁止这些行为,但是这些行为会有不确定的结果。

一种可能的方式是使用keytags来干预key的分布,当然,这需要手工的干预。

另外一个限制是正在使用的shards是不能被改变的,因为所有的sharding都是预分片的。

注:

如果希望使用可以改变的shards,可以使用yaourt-dynamicshardingimplementation(一个jedis的实现分支)。

ShardedJedis的使用方法:

1.定义shards:

Listshards=newArrayList();

JedisShardInfosi=newJedisShardInfo("localhost",6379);

si.setPassword("foobared");

shards.add(si);

si=newJedisShardInfo("localhost",6380);

si.setPassword("foobared");

shards.add(si);

2.a)直接使用:

ShardedJedisjedis=newShardedJedis(shards);

jedis.set("a","foo");

jedis.disconnect;

2.b)或使用连接池:

ShardedJedisPoolpool=newShardedJedisPool(newConfig(),shards);

ShardedJedisjedis=pool.getResource();

jedis.set("a","foo");

....//doyourworkhere

pool.returnResource(jedis);

....//afewmomentslater

ShardedJedisjedis2=pool.getResource();

jedis.set("z","bar");

pool.returnResource(jedis);

pool.destroy();

判断使用的是那个shards:

ShardInfosi=jedis.getShardInfo(key);

si.getHost/getPort/getPassword/getTimeout/getName

也可以通过keytags来确保key位于相同的shard。

如:

ShardedJedisjedis=newShardedJedis(shards,

ShardedJedis.DEFAULT_KEY_TAG_PATTERN);

这样,默认的keytags是”{}”,这表示在”{}”内的字符会用于决定使用那个shard。

如:

jedis.set("foo{bar}","12345");

jedis.set("car{bar}","877878");

会使用同一个shard。

注:

如果key和keytag不匹配,会使用原来的key作为选择shard的key。

使用ShardedJedisPipeline

ShardedJedisPipeline其实是一个很鸡肋的功能。

为了能在ShardedJedis中平滑的支持redis的pipeline的功能,ShardedJedis通过ShardedJedisPipeline类对pipeline提供了支持。

简单的说,ShardedJedis是通过向每个用到的shard发起pipeline来实现ShardedJedisPipeline的功能,这种方式如果累积的key不够多,很难达到提高效率的目的。

如果需要在ShardedJedis中使用pipeline,还是建议尽量通过keytag将关联的key放到同一shard之中。

ShardedJedisPipeline简单的示例代码如下:

ShardedJedisjedis=newShardedJedis(shards);

ShardedJedisPipelinep=jedis.pipelined();

p.set("foo","bar");

p.get("foo");

Listresults=p.syncAndReturnAll();

//assertEquals(2,results.size());

//assertEquals("OK",results.get(0));

//assertEquals("bar",results.get

(1));

ShardedJedisPipeline相对复杂的示例代码:

ShardedJedisjedis=newShardedJedis(shards);

jedis.set("string","foo");

jedis.lpush("list","foo");

jedis.hset("hash","foo","bar");

jedis.zadd("zset",1,"foo");

jedis.sadd("set","foo");

ShardedJedisPipelinep=jedis.pipelined();

Responsestring=p.get("string");

Responsedel=p.del("string");

ResponseemptyString=p.get("string");

Responselist=p.lpop("list");

Responsehash=p.hget("hash","foo");

Response>zset=p.zrange("zset",0,-1);

Responseset=p.spop("set");

Responseblist=p.exists("list");

Responsezincrby=p.zincrby("zset",1,"foo");

Responsezcard=p.zcard("zset");

p.lpush("list","bar");

Response>lrange=p.lrange("list",0,-1);

Response>hgetAll=p.hgetAll("hash");

p.sadd("set","foo");

Response>smembers=p.smembers("set");

Response>zrangeWithScores=p.zrangeWithScores("zset",0,

-1);

p.sync();

assertEquals("foo",string.get());

assertEquals(Long.valueOf

(1),del.get());

assertNull(emptyString.get());

assertEquals("foo",list.get());

assertEquals("bar",hash.get());

assertEquals("foo",zset.get().iterator().next());

assertEquals("foo",set.get());

assertFalse(blist.get());

assertEquals(Double.valueOf

(2),zincrby.get());

assertEquals(Long.valueOf

(1),zcard.get());

assertEquals(1,lrange.get().size());

assertNotNull(hgetAll.get().get("foo"));

assertEquals(1,smembers.get().size());

assertEquals(1,zrangeWithScores.get().size());

使用jedis的对象池

jedis通过commons-pool来提供其对象池的功能,其对象池类有JedisPool和ShardedJedisPool,面向普通的redis连接池和pre-sharding的redis连接池。

在连接池的使用和配置层面,这两个类基本没什么差别。

配置jedis的连接池,一般通过JedisPoolConfig类完成,其提供了一个不同于基类的默认值,当然也可以通过mons.pool.impl.GenericObjectPool.Config类来配置,这个类的默认值我们可以在commons-pool对象池配置的小节中看到。

对象池的使用

jedis创建对象池的方式:

JedisPoolpool=newJedisPool(newJedisPoolConfig(),"localhost");

使用池中的对象,是通过JedisPool的getResource和returnResource来得到和归还资源:

Jedisjedis=pool.getResource();

try{

///...dostuffhere...forexample

jedis.set("foo","bar");

Stringfoobar=jedis.get("foo");

jedis.zadd("sose",0,"car");jedis.zadd("sose",0,"bike");

Setsose=jedis.zrange("sose",0,-1);

}catch(JedisConnectionExceptione){

//returnBrokenResourcewhenthestateoftheobjectisunrecoverable

if(null!

=jedis){

pool.returnBrokenResource(jedis);

jedis=null;

}

}finally{

///...it'simportanttoreturntheJedisinstancetothepoolonceyou'vefinishedusingit

if(null!

=jedis)

pool.returnResource(jedis);

}

///...whenclosingyourapplication:

pool.destroy();

commons-pool对象池配置

jedis的对象池是通过apache的commons-pool实现的。

其对象池的配置是通过mons.pool.impl.GenericObjectPool.Config类完成。

Config是一个简单的值对象类,其成员都有预设的默认值。

我们将Config类的各个成员的配置含义描述如下:

⏹maxActive

控制池中对象的最大数量。

默认值是8,如果是负值表示没限制。

⏹maxIdle

控制池中空闲的对象的最大数量。

默认值是8,如果是负值表示没限制。

⏹minIdle

控制池中空闲的对象的最小数量。

默认值是0。

⏹whenExhaustedAction

指定池中对象被消耗完以后的行为,有下面这些选择:

>>WHEN_EXHAUSTED_FAIL0

>>WHEN_EXHAUSTED_GROW2

>>WHEN_EXHAUSTED_BLOCK1

如果是WHEN_EXHAUSTED_FAIL,当池中对象达到上限以后,继续borrowObject会抛出NoSuchElementException异常。

如果是WHEN_EXHAUSTED_GROW,当池中对象达到上限以后,会创建一个新对象,并返回它。

如果是WHEN_EXHAUSTED_BLOCK,当池中对象达到上限以后,会一直等待,直到有一个对象可用。

这个行为还与maxWait有关,如果maxWait是正数,那么会等待maxWait的毫秒的时间,超时会抛出NoSuchElementException异常;如果maxWait为负值,会永久等待。

whenExhaustedAction的默认值是WHEN_EXHAUSTED_BLOCK,maxWait的默认值是-1。

⏹maxWait

whenExhaustedAction如果是WHEN_EXHAUSTED_BLOCK,指定等待的毫秒数。

如果maxWait是正数,那么会等待maxWait的毫秒的时间,超时会抛出NoSuchElementException异常;如果maxWait为负值,会永久等待。

maxWait的默认值是-1。

⏹testOnBorrow

如果testOnBorrow被设置,pool会在borrowObject返回对象之前使用PoolableObjectFactory的validateObject来验证这个对象是否有效,要是对象没通过验证,这个对象会被丢弃,然后重新选择一个新的对象。

testOnBorrow的默认值是false。

⏹testOnReturn

如果testOnReturn被设置,pool会在returnObject的时候通过PoolableObjectFactory的validateObject方法验证对象,如果对象没通过验证,对象会被丢弃,不会被放到池中。

testOnReturn的默认值是false。

⏹testWhileIdle

指定idle对象是否应该使用PoolableObjectFactory的validateObject校验,如果校验失败,这个对象会从对象池中被清除。

这个设置仅在timeBetweenEvictionRunsMillis被设置成正值(>0)的时候才会生效。

testWhileIdle的默认值是false。

⏹timeBetweenEvictionRunsMillis

指定驱逐线程的休眠时间。

如果这个值不是正数(>0),不会有驱逐线程运行。

timeBetweenEvictionRunsMillis的默认值是-1。

⏹numTestsPerEvictionRun

设置驱逐线程每次检测对象的数量。

这个设置仅在timeBetweenEvictionRunsMillis被设置成正值(>0)的时候才会生效。

numTestsPerEvictionRun的默认值是3。

⏹minEvictableIdleTimeMillis

指定最小的空闲驱逐的时间间隔(空闲超过指定的时间的对象,会被清除掉)。

这个设置仅在timeBetweenEvictionRunsMillis被设置成正值(>0)的时候才会生效。

minEvictableIdleTimeMillis默认值是30分钟。

⏹softMinEvictableIdleTimeMillis

与minEvictableIdleTimeMillis类似,也是指定最小的空闲驱逐的时间间隔(空闲超过指定的时间的对象,会被清除掉),不过会参考minIdle的值,只有idle对象的数量超过minIdle的值,对象才会被清除。

这个设置仅在timeBetweenEvictionRunsMillis被设置成正值(>0)的时候才会生效,并且这个配置能被minEvictableIdleTimeMillis配置取代(minEvictableIdleTimeMillis配置项的优先级更高)。

softMinEvictableIdleTimeMillis的默认值是-1。

⏹lifo

pool可以被配置成LIFO队列(last-in-first-out)或FIFO队列(first-in-first-out),来指定空闲对象被使用的次序。

lifo的默认值是true。

JedisPoolConfig的调整

jedis的对象池是通过commons-pool实现的,对对象池的配置应该通过JedisPoolConfig来完成,jedis提供了自己的配置参数:

publicclassJedisPoolConfigextendsConfig{

publicJedisPoolConfig(){

//defaultstomakeyourlifewithconnectionpooleasier:

setTestWhileIdle(true);

setMinEvictableIdleTimeMillis(60000);

setTimeBetweenEvictionRunsMillis(30000);

setNumTestsPerE

展开阅读全文
相关搜索

当前位置:首页 > 高中教育 > 小学教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1