新聞中心
利用Redis解決獲取連接阻塞問題

10余年的商南網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。全網(wǎng)營(yíng)銷推廣的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整商南建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)建站從事“商南網(wǎng)站設(shè)計(jì)”,“商南網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
在開發(fā)中有時(shí)我們需要使用連接池來訪問數(shù)據(jù)庫或者其他資源,使用連接池可以更加高效地利用資源。但是使用連接池的過程中我們可能會(huì)遇到一個(gè)“獲取連接阻塞”的問題,這在高并發(fā)情況下會(huì)導(dǎo)致服務(wù)出現(xiàn)延遲,而 Redis 就是一個(gè)解決這個(gè)問題的好工具。下面我們將詳細(xì)介紹如何利用 Redis 解決該問題。
1. 獲取連接阻塞問題的原因
連接池的連接數(shù)量是有限的,當(dāng)連接池中的連接全部被占用時(shí),需要馬上處理某個(gè)新的請(qǐng)求時(shí),就會(huì)出現(xiàn)獲取連接阻塞的問題。因?yàn)榇藭r(shí)新請(qǐng)求需要等待已占用的連接釋放出來,才能獲取連接并完成操作,這就會(huì)導(dǎo)致請(qǐng)求阻塞,服務(wù)出現(xiàn)延遲。
2. Redis解決獲取連接阻塞
Redis 通過將連接池的數(shù)量劃分成多個(gè)不同的區(qū)域,并針對(duì)每個(gè)區(qū)域使用不同的 timeout 時(shí)間來解決獲取連接阻塞的問題。
我們客戶端請(qǐng)求連接池時(shí)就將連接池的連接分成多個(gè)區(qū)域,每個(gè)區(qū)域內(nèi)的連接數(shù)量相同。 然后對(duì)于每個(gè)區(qū)域設(shè)置不同的 timeout 時(shí)間:
// Redis 客戶端連接獲取
CONN = redis_conn_pool.getConnFromPool()
// 定義 timeout 數(shù)組
long[] timeout = new long[] {0L, 300L, 500L, 1000L, 5000L};
// 根據(jù)客戶端請(qǐng)求的等級(jí)獲取相應(yīng)的 timeout 值
long t = timeout[level];
if (conn == null) {
// 如果指定 timeout 的情況下獲取連接超時(shí)時(shí)間為 t
conn = redis_conn_pool.getPooledConn(t, TimeUnit.MILLISECONDS);
}
每個(gè)請(qǐng)求的等級(jí)不同,我們可以根據(jù)不同的等級(jí)來獲取連接池中的連接。不同等級(jí)獲取的連接所對(duì)應(yīng)的區(qū)域也不同,使用相應(yīng)的 timeout 值,若在 timeout 時(shí)間內(nèi)仍無法獲取到連接,則放棄該次請(qǐng)求。
在具體實(shí)現(xiàn)中,我們通常先創(chuàng)建一個(gè) Redis 連接池來管理連接的分配和釋放,然后通過 jedis 類庫來進(jìn)行具體的操作。下面是一個(gè)簡(jiǎn)單的 Redis 連接池的實(shí)現(xiàn)例子:
public class RedisConnectionPool {
private static final Logger LOGGER = LoggerFactory.getLogger(RedisConnectionPool.class);
private JedisPool jedisPool = null;
public RedisConnectionPool(String host, int port, int database) {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(100);
config.setMaxIdle(5);
config.setMaxWtMillis(1000);
config.setTestOnBorrow(true);
this.jedisPool = new JedisPool(config, host, port, 5000, null, database);
}
/**
* 獲取 Redis 連接
*/
public Jedis getConnFromPool() {
Jedis jedis = null;
try {
jedis = this.jedisPool.getResource();
LOGGER.info("get Redis connection success!");
} catch (Exception e) {
LOGGER.error("get Redis connection fled: " + e.getMessage());
}
return jedis;
}
/**
* 從 Redis 連接池中獲取連接
* @param timeout 超時(shí)時(shí)間
* @param timeUnit 時(shí)間單位
*/
public Jedis getPooledConn(long timeout, TimeUnit timeUnit) {
long start = System.currentTimeMillis();
long maxWtTime = TimeUnit.MILLISECONDS.convert(timeout, timeUnit);
Jedis conn;
while ((conn = jedisPool.getResource()) == null) {
long now = System.currentTimeMillis();
if (now - start > maxWtTime) {
LOGGER.warn("get Redis connection timeout!");
return null;
}
Thread.sleep(10);
}
LOGGER.info("get Redis connection success!");
return conn;
}
/**
* 回收 Redis 連接
*/
public void returnConnToPool(Jedis jedis) {
if (jedis != null) {
jedis.close();
}
}
/**
* 銷毀 Redis 連接池
*/
public void destroy() {
jedisPool.destroy();
LOGGER.warn("destroy Redis connection pool success!");
}
}
3. 總結(jié)
在高并發(fā)情況下,使用連接池是提高性能的一種方式。但當(dāng)連接池得不到充分利用時(shí),就會(huì)出現(xiàn)“獲取連接阻塞”的問題。通過 Redis 的實(shí)現(xiàn)方式可以很好地解決此問題。在具體實(shí)現(xiàn)過程中,我們需要注意連接池的連接分配與釋放,并請(qǐng)記得關(guān)閉連接并銷毀連接池。
成都服務(wù)器租用選創(chuàng)新互聯(lián),先試用再開通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)提供簡(jiǎn)單好用,價(jià)格厚道的香港/美國(guó)云服務(wù)器和獨(dú)立服務(wù)器。物理服務(wù)器托管租用:四川成都、綿陽、重慶、貴陽機(jī)房服務(wù)器托管租用。
當(dāng)前文章:利用Redis解決獲取連接阻塞問題(redis獲取連接阻塞)
本文URL:http://m.fisionsoft.com.cn/article/dhgcigp.html


咨詢
建站咨詢
