Redis筆記3:Jedis連線自動釋放
一、正常釋放連線
正常釋放連線的程式碼如下:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisTest {
public static void main(String[] args) {
JedisPoolConfig config = new JedisPoolConfig();
//最大連線數, 應用自己評估,不要超過AliCloudDB for Redis每個例項最大的連線數
config.setMaxTotal(5);
String host = "Your real hostname or host ip";
String password = "Your real password";
JedisPool pool = new JedisPool(config, host, 6379, 3000, password);
Jedis jedis = null;
for(int i = 0; i < 10; i++) {
try {
jedis = pool.getResource();
jedis.set("foo", "bar");
System.out.println("第" + (i+1) + "個連線, 得到的值為" + jedis.get("foo"));
} finally {
if (jedis != null) {
jedis.close();
}
}
}
pool.close();
}
}
執行結果:
第1個連線, 得到的值為bar
第2個連線, 得到的值為bar
第3個連線, 得到的值為bar
第4個連線, 得到的值為bar
第5個連線, 得到的值為bar
第6個連線, 得到的值為bar
第7個連線, 得到的值為bar
第8個連線, 得到的值為bar
第9個連線, 得到的值為bar
第10個連線, 得到的值為bar
分析:這裡透過config.setMaxTotal(5);把連線池的最大連線設為五個,測試的時候在迴圈裡啟用了10個連線,並都正常列印出了結果。這是因為jedis連線用完了就關閉的緣故。注意到這裡使用單執行緒進行測試,連線池的最大連線數設為1就能滿足需求。
二、忘記釋放連線
有時候程式設計師有可能忘了關閉連線,程式碼如下:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisTest {
public static void main(String[] args) {
JedisPoolConfig config = new JedisPoolConfig();
//最大連線數, 應用自己評估,不要超過AliCloudDB for Redis每個例項最大的連線數
config.setMaxTotal(5);
String host = "Your real hostname or host ip";
String password = "Your real password";
JedisPool pool = new JedisPool(config, host, 6379, 3000, password);
Jedis jedis = null;
for(int i = 0; i < 10; i++) {
try {
jedis = pool.getResource();
jedis.set("foo", "bar");
System.out.println("第" + (i+1) + "個連線, 得到的值為" + jedis.get("foo"));
} finally {
if (jedis != null) {
// jedis.close();
}
}
}
pool.close();
}
}
執行結果:
第1個連線, 得到的值為bar
第2個連線, 得到的值為bar
第3個連線, 得到的值為bar
第4個連線, 得到的值為bar
第5個連線, 得到的值為bar
分析:這個程式碼跟上一步的程式碼比起來,只是把redis.close();這一行註釋起來了,相當於程式設計師忘寫這行程式碼。導致的結果就是隻能得到5個結果。這是因為連線池的最大連線數設為5,然後測試時啟用了10個連線,因為連線沒有被釋放,當最大連線數被用完後,後面的5個連線就連不上了,只能乾等著。
三、將Jedis的連線和釋放進行封裝
為了避免上述忘記釋放連線的情況,我們們可以把連線的程式碼封裝到RedisUtil類裡,在RedisUtil內部實現釋放連線的邏輯,這樣程式設計師在外部呼叫的時候不需要釋放也無法釋放,從而達到了安全連線的目的。
封裝程式碼如下:
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* @功能:Redis通用類
* @作者:鄭海樹
* @日期:2016-1-17
*/
public class RedisUtil {
private JedisPool pool = null;
/**
* @功能:帶引數的建構函式
* @引數:host,主機名或主機IP
* @引數:port,埠
* @引數:password,訪問Redis資料庫的密碼
*/
public RedisUtil(String host, int port, String password) {
if (pool == null) {
JedisPoolConfig config = new JedisPoolConfig();
// 控制一個pool可分配多少個jedis例項,透過pool.getResource()來獲取;
// 如果賦值為-1,則表示不限制;如果pool已經分配了maxTotal個jedis例項,則此時pool的狀態為exhausted(耗盡)。
config.setMaxTotal(1);
pool = new JedisPool(config, host, port, 60000, password);
}
}
/**
* @功能:透過Redis的key獲取值,並釋放連線資源
* @引數:key,鍵值
* @返回: 成功返回value,失敗返回null
*/
public String get(String key){
Jedis jedis = null;
String value = null;
try {
jedis = pool.getResource();
value = jedis.get(key);
} catch (Exception e) {
pool.returnBrokenResource(jedis);
e.printStackTrace();
} finally {
if(null != pool) {
pool.returnResource(jedis);
}
}
return value;
}
/**
* @功能:向redis存入key和value(如果key已經存在 則覆蓋),並釋放連線資源
* @引數:key,鍵
* @引數:value,與key對應的值
* @返回:成功返回“OK”,失敗返回“0”
*/
public String set(String key,String value){
Jedis jedis = null;
try {
jedis = pool.getResource();
return jedis.set(key, value);
} catch (Exception e) {
pool.returnBrokenResource(jedis);
e.printStackTrace();
return "0";
} finally {
if(null != pool) {
pool.returnResource(jedis);
}
}
}
}
測試程式碼:
public class RedisUtilTest {
public static void main(String[] args) {
String host = "Your real hostname or host ip";
String password = "Your real password";
int port = 6379;
RedisUtil redisUtil = new RedisUtil(host, port, password);
for(int i = 0; i < 10; i++) {
redisUtil.set("foo", "bar");
System.out.println("第" + (i+1) + "個連線, 得到的值為" + redisUtil.get("foo"));
}
}
}
執行結果:
第1個連線, 得到的值為bar
第2個連線, 得到的值為bar
第3個連線, 得到的值為bar
第4個連線, 得到的值為bar
第5個連線, 得到的值為bar
第6個連線, 得到的值為bar
第7個連線, 得到的值為bar
第8個連線, 得到的值為bar
第9個連線, 得到的值為bar
第10個連線, 得到的值為bar
分析:在RedisUtil中特意把最大連線數設為1,且在set和get方法中實現了釋放連線的邏輯。這樣,在不考慮多執行緒的情況下,10個迴圈可以反覆利用一個連線。
四、後續工作
1 在實際專案中,多數情況下遇到的是併發連線的情況,應該利用多執行緒寫一個併發測試,並且增大引數來判斷效率問題。
2 這裡的RedisUtil僅實現了最基本的功能,可考慮將其擴充套件成一個通用類。這樣程式設計師在處理Redis連線的時候,統一跟RedisUtil打交道即可,不需要再訪問Jedis.class和JedisPool.class。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29485627/viewspace-1977880/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Redis筆記2:Jedis連線池Redis筆記
- Redis學習記錄(二)--使用Jedis連線Redis
- Jedis使用連線池操作redis叢集Redis
- redis 原始碼分析:Jedis 哨兵模式連線原理Redis原始碼模式
- MySQL筆記3——內連線/外連線、多表連線MySql筆記
- FireFox記憶體自動釋放Firefox記憶體
- redis驅動-jedis實現1Redis
- Hyperf 如何快速釋放 DB 連線
- MYSQL學習筆記23: 多表查詢(自連線內連線+左右外連線)MySql筆記
- Web - Redis & JedisWebRedis
- Redis(15) jedisRedis
- jedis操作 redisRedis
- 解決使用jedis連線是報DENIED Redis is running in protected mode錯誤Redis
- Jedis 連線 Redis報JedisConnectionException: java.net.ConnectException: Connection refusedRedisExceptionJava
- mysql連線池爆滿,釋放程式長連線殭屍程式MySql
- 重拾 ObjC 自動釋放池OBJ
- win10如何設定自動釋放記憶體_win10怎麼設定自動清理系統垃圾釋放記憶體Win10記憶體
- 理解 TCP(三):連線的建立和釋放TCP
- Java 客戶端 Jedis和JedisPool 連線池Java客戶端
- java try(){}catch(){}自動資源釋放Java
- Redis學習筆記(Jedis&資料型別&持久化&主從複製)Redis筆記資料型別持久化
- [學習筆記]使用Docker+Jenkin自動化流水線釋出.Net應用筆記Docker
- 記一次websocket的自動斷開連線Web
- TCP建立連線三次握手和釋放連線四次握手TCP
- redis(二)redis概述與jedis的使用Redis
- ODBC資料庫連線------java學習筆記之3資料庫Java筆記
- 自動推理筆記筆記
- Linux釋放記憶體及手動釋放Oracle共享記憶體段Linux記憶體Oracle
- 自動釋放系統資源(轉載)
- java操作redis。jedis使用apiJavaRedisAPI
- 【網路協議】TCP連線的建立和釋放協議TCP
- 3.DQL資料查詢語言(內連線,外連線,自連線)
- redis個人原始碼分析筆記3---redis的事件驅動原始碼分析Redis原始碼筆記事件
- Python連線Redis連線配置PythonRedis
- vector 避免記憶體頻繁分配釋放與手動釋放vector記憶體記憶體
- Jedis連線池究竟是何物|得物技術
- Jedis 與 MySQL的連線執行緒安全問題MySql執行緒
- 18 Redis 連線Redis