??Jedis有直連方式领猾,所謂直連指的是Jedis每次都會(huì)新建TCP連接钉嘹,使用后在斷開連接,對于平凡訪問Redis的場景顯然不是高效的使用方式娃属,如圖:
??因此生產(chǎn)環(huán)境一般使用連接池的方式對Jedis連接池進(jìn)行管理爆存,如圖:
??Jedis對象預(yù)先放在池子中(JedisPool)蛉顽,每次要連接Redis,只需要在池子中借先较,用完了在歸還給池子携冤。
??客戶端連接Redis使用的是TCP協(xié)議,直連的方式每次需要建立TCP連接闲勺,而連接池的方式是可以預(yù)先初始化好Jedis連接曾棕,所以每次只需要從Jedis連接池借用即可,而借用和歸還操作是在本地進(jìn)行的菜循,只有少量的并發(fā)同步開銷翘地,遠(yuǎn)遠(yuǎn)小于新建TCP連接的開銷。另外直連的方式無法限制Jedis對象的個(gè)數(shù)癌幕,在極端情況下可能會(huì)造成連接泄漏子眶,而連接池的形式可以有效的保護(hù)和控制資源的使用。但是直連的方式也并不是一無是處序芦,下表給出兩種方式各自的優(yōu)劣勢:
- 直連 ?優(yōu)點(diǎn):簡單方便,適用于少量長期連接的場景粤咪,缺點(diǎn):1>存在每次新建/關(guān)閉TCP連接開銷谚中。2>資源無法控制,極端情況會(huì)出現(xiàn)連接泄漏寥枝。3>Jedis對象線程不安全宪塔。
- 連接池?優(yōu)點(diǎn):1>無需每次連接都生成Jedis對象,降低開銷囊拜。2>使用連接池的形式保護(hù)和控制資源的使用某筐。缺點(diǎn):相對于直連,使用相對麻煩冠跷,尤其在資源的管理上需要很多參數(shù)來保證南誊,一旦不合理也會(huì)出現(xiàn)問題。
??Jedis提供了JedisPool這個(gè)類作為對Jedis的連接池蜜托,同時(shí)使用了Apache的通用對象池工具common-pool作為資源的管理工具抄囚,下面是使用JedisPool操作Redis的代碼示例:
1)Jedis連接池(通常JedisPool是單例的):
//common-pool連接池配置,這里使用默認(rèn)配置橄务,后面小節(jié)會(huì)介紹具體配置說明
GenericObjectPoolConfig poolConfig=new GenericObjectPoolConfig();
//初始化Jedis連接池
JedisPool jedisPool=new JedisPool(poolConfig,"127.0.0.1",6379);
- 獲取Jedis對象不再是直接生成一個(gè)Jedis對象進(jìn)行直連幔托,而是從連接池直接獲取,代碼如下:
Jedis jedis =null;
try {
//1.從連接池獲取jedis對象
jedis=jedisPool.getResource();
//2.執(zhí)行操作
jedis.get("hello");
} catch (Exception e) {
logger.error(e.getMessage(),e);
}finally{
if(jedis!=null){
//如果使用JedisPool,close操作不是關(guān)閉連接,代表歸還連接池
jedis.close();
}
}
??這里可以看到finally中依然是jedis.close()操作重挑,為什么會(huì)把連接關(guān)閉呢嗓化,這不和連接池的原則違背嗎?但實(shí)際上Jedis的close()實(shí)現(xiàn)方式如下:
public void close(){
//使用Jedis連接池
if(dataSource!=null){
if(client.isBroken()){
this.dataSource.returnBrokenResource(this);
}else{
this.dataSource.returnResource(this);
}
//直連
}else{
client.close();
}
}
參數(shù)說明:
- dataSource!=null代表使用的是連接池谬哀,所以jedis.close()代表歸還連接給連接池刺覆,而且Jedis會(huì)判斷當(dāng)前連接是否已經(jīng)斷開。
- dataSource=null代表直連玻粪,jedis.close()代表關(guān)閉連接隅津。
??前面GenericObjectPoolConfig使用的是默認(rèn)配置,實(shí)際它提供有很多參數(shù)劲室,例如池子中最大連接數(shù)伦仍,最大空閑連接數(shù),最小空閑連接數(shù)很洋,連接活性檢測充蓝,等等,例如下面代碼:
GenericObjectPoolConfig poolConfig=new GenericObjectPoolConfig();
//設(shè)置最大連接數(shù)為默認(rèn)值的5倍
poolConfig.setMaxTotal(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL*5);
//設(shè)置最大空閑連接數(shù)為默認(rèn)值的3倍
poolConfig.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE*3);
//設(shè)置最小空閑連接數(shù)為默認(rèn)值的2倍
poolConfig.setMinIdle(GenericObjectPoolConfig. DEFAULT_MIN_IDLE*2);
//設(shè)置開啟JMX功能
poolConfig.SetJmxEnabled(true);
//設(shè)置連接池沒有連接后客戶端的最大等待時(shí)間(單位為毫秒)
poolConfig.setMaxWaitMillis(3000);
GenericObjectPoolConfig的其他屬性:
基本參數(shù)
lifo ?//GenericObjectPool 提供了后進(jìn)先出(LIFO)與先進(jìn)先出(FIFO)兩種行為模式的池喉磁。默認(rèn)為true谓苟,即當(dāng)池中有空閑可用的對象時(shí),調(diào)用borrowObject方法會(huì)返回最近(后進(jìn))的實(shí)例
fairness ?//當(dāng)從池中獲取資源或者將資源還回池中時(shí) 是否使用java.util.concurrent.locks.ReentrantLock.ReentrantLock 的公平鎖機(jī)制,默認(rèn)為false
數(shù)量控制參數(shù)
maxTotal ?//鏈接池中最大連接數(shù),默認(rèn)為8
maxIdle ?//鏈接池中最大空閑的連接數(shù),默認(rèn)也為8
minIdle ?//連接池中最少空閑的連接數(shù),默認(rèn)為0
超時(shí)參數(shù)
maxWaitMillis ?//當(dāng)連接池資源耗盡時(shí)协怒,等待時(shí)間涝焙,超出則拋異常,默認(rèn)為-1即永不超時(shí)
blockWhenExhausted ?//連接耗盡時(shí)是否阻塞, false報(bào)異常,ture阻塞直到超時(shí), 默認(rèn)true孕暇。當(dāng)這個(gè)值為true的時(shí)候仑撞,maxWaitMillis參數(shù)才能生效。為false的時(shí)候妖滔,當(dāng)連接池沒資源隧哮,則立馬拋異常。默認(rèn)為true
test參數(shù)
testOnCreate ?//默認(rèn)false座舍,create的時(shí)候檢測是有有效沮翔,如果無效則從連接池中移除,并嘗試獲取繼續(xù)獲取
testOnBorrow ?//默認(rèn)false曲秉,borrow的時(shí)候檢測是有有效采蚀,如果無效則從連接池中移除,并嘗試獲取繼續(xù)獲取
testOnReturn ?//默認(rèn)false承二,return的時(shí)候檢測是有有效搏存,如果無效則從連接池中移除,并嘗試獲取繼續(xù)獲取
testWhileIdle ?//默認(rèn)false矢洲,在evictor線程里頭璧眠,當(dāng)evictionPolicy.evict方法返回false時(shí),而且testWhileIdle為true的時(shí)候則檢測是否有效,如果無效則移除
檢測參數(shù)
timeBetweenEvictionRunsMillis ?//空閑鏈接檢測線程檢測的周期责静,毫秒數(shù)袁滥。如果為負(fù)值,表示不運(yùn)行檢測線程灾螃。默認(rèn)為-1.
numTestsPerEvictionRun ?//在每次空閑連接回收器線程(如果有)運(yùn)行時(shí)檢查的連接數(shù)量题翻,默認(rèn)為3
minEvictableIdleTimeMillis ?//連接空閑的最小時(shí)間,達(dá)到此值后空閑連接將可能會(huì)被移除腰鬼。默認(rèn)為1000L 60L 30L
softMinEvictableIdleTimeMillis ?//連接空閑的最小時(shí)間嵌赠,達(dá)到此值后空閑鏈接將會(huì)被移除,且保留minIdle個(gè)空閑連接數(shù)熄赡。默認(rèn)為-1.
evictionPolicyClassName ?//evict策略的類名姜挺,默認(rèn)為org.apache.commons.pool2.impl.DefaultEvictionPolicy
其他
jmxEnabled ?//是否開啟jmx監(jiān)控,如果應(yīng)用開啟了jmx端口并且jmxEnabled設(shè)置為true彼硫,就可以通過jconsole或者jvisualvm看到關(guān)于連接池的相關(guān)統(tǒng)計(jì)炊豪,有助于了解連接池的使用情況,并且可以針對其做監(jiān)控統(tǒng)計(jì)拧篮,默認(rèn)是true词渤。
evictionPolicyClassName ?//設(shè)置的逐出策略類名, 默認(rèn)"org.apache.commons.pool2.impl.DefaultEvictionPolicy"(當(dāng)連接超過最大空閑時(shí)間,或連接數(shù)超過最大空閑連接數(shù))