連接redis集羣:
package com.ssq.dmp.utils.jedis;
import redis.clients.jedis.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.logging.Logger;
/**
* Jedis工具類
*/
public class JedisConnectionUtil {
private final static Logger logger = Logger.getLogger(JedisPoolUtil.class.getName());
/**
* jedis哨兵集羣連接單例對象
*/
private static JedisSentinelPool jedisSentinelPool = null;
/**
* jedis集羣連接單例對象
*/
private static JedisCluster jedisCluster = null;
private static Properties getJedisProperties() {
Properties config = new Properties();
InputStream is = null;
try {
is = JedisConnectionUtil.class.getClassLoader().getResourceAsStream("jedisConfig.properties");
config.load(is);
} catch (IOException e) {
logger.info(e.getMessage());
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
logger.info(e.getMessage());
}
}
}
return config;
}
/**
* 創建JedisCluster
* JedisCluster不需要單獨構建連接池,其已經基於連接池實現
*/
private static void createJedisCluster(){
//讀取配置文件
Properties prop = getJedisProperties();
//jedisCluster配置
String[] serverArray = prop.getProperty("servers").split(",");
int connectionTimeout = Integer.parseInt(prop.getProperty("connectionTimeout"));
int soTimeout = Integer.parseInt(prop.getProperty("soTimeout"));
int maxAttempts = Integer.parseInt(prop.getProperty("maxAttempts"));
//jedis連接池配置
// 建立連接池配置參數
JedisPoolConfig config = new JedisPoolConfig();
// 設置最大連接數
config.setMaxTotal(new Integer(prop.getProperty("maxTotal")));
// 設置最大阻塞時間,記住是毫秒數milliseconds
config.setMaxWaitMillis(new Integer(prop.getProperty("maxWaitMillis")));
// 設置最大空間連接數
config.setMaxIdle(new Integer(prop.getProperty("maxIdle")));
// 設置最小空間連接數
config.setMinIdle(new Integer(prop.getProperty("minIdle")));
// jedis實例是否可用
boolean testOnBorrow = !prop.getProperty("testOnBorrow").equals("false");
config.setTestOnBorrow(testOnBorrow);
//#從連接池獲取不到連接則阻塞
boolean blockWhenExhausted = !prop.getProperty("blockWhenExhausted").equals("false");
config.setBlockWhenExhausted(blockWhenExhausted);
//#連接對象後進先出
boolean lifo = !prop.getProperty("lifo").equals("false");
config.setLifo(lifo);
//#歸還連接到池時測試連接
boolean testOnReturn = !prop.getProperty("testOnReturn").equals("false");
config.setTestOnReturn(testOnReturn);
//#測試連接池空閒的連接
boolean testWhileIdle = !prop.getProperty("testWhileIdle").equals("false");
config.setTestWhileIdle(testWhileIdle);
//#測試連接池空閒連接的時間間隔,testWhileIdle=true時生效
config.setTimeBetweenEvictionRunsMillis(new Integer(prop.getProperty("timeBetweenEvictionRunsMillis")));
Set<HostAndPort> nodes = new HashSet<>();
for (String ipPort : serverArray) {
String[] ipPortPair = ipPort.split(":");
nodes.add(new HostAndPort(ipPortPair[0].trim(), Integer.parseInt(ipPortPair[1].trim())));
}
//注意:這裏超時時間不要太短,他會有超時重試機制
jedisCluster = new JedisCluster(nodes, connectionTimeout, soTimeout, maxAttempts,config);
}
/**
* 創建sentinel連接池
*/
private static void createJedisSentinelPool(){
//讀取jedis配置文件
Properties prop = getJedisProperties();
//jedis連接池配置
// 建立連接池配置參數
JedisPoolConfig config = new JedisPoolConfig();
// 設置最大連接數
config.setMaxTotal(new Integer(prop.getProperty("maxTotal")));
// 設置最大阻塞時間,記住是毫秒數milliseconds
config.setMaxWaitMillis(new Integer(prop.getProperty("maxWaitMillis")));
// 設置最大空間連接數
config.setMaxIdle(new Integer(prop.getProperty("maxIdle")));
// 設置最小空間連接數
config.setMinIdle(new Integer(prop.getProperty("minIdle")));
// jedis實例是否可用
boolean testOnBorrow = !prop.getProperty("testOnBorrow").equals("false");
config.setTestOnBorrow(testOnBorrow);
//#從連接池獲取不到連接則阻塞
boolean blockWhenExhausted = !prop.getProperty("blockWhenExhausted").equals("false");
config.setBlockWhenExhausted(blockWhenExhausted);
//#連接對象後進先出
boolean lifo = !prop.getProperty("lifo").equals("false");
config.setLifo(lifo);
//#歸還連接到池時測試連接
boolean testOnReturn = !prop.getProperty("testOnReturn").equals("false");
config.setTestOnReturn(testOnReturn);
//#測試連接池空閒的連接
boolean testWhileIdle = !prop.getProperty("testWhileIdle").equals("false");
config.setTestWhileIdle(testWhileIdle);
//#測試連接池空閒連接的時間間隔,testWhileIdle=true時生效
config.setTimeBetweenEvictionRunsMillis(new Integer(prop.getProperty("timeBetweenEvictionRunsMillis")));
//獲取redis密碼
//String password = prop.getProperty("PASSWORD");
String masterName = prop.getProperty("MASTER");
String sentinel_1 = prop.getProperty("SENTINEL_1");
String sentinel_2 = prop.getProperty("SENTINEL_2");
String sentinel_3 = prop.getProperty("SENTINEL_3");
Set<String> sentinels = new HashSet<>();
sentinels.add(sentinel_1);
sentinels.add(sentinel_2);
sentinels.add(sentinel_3);
jedisSentinelPool = new JedisSentinelPool(masterName, sentinels, config);
}
/**
* 在多線程環境同步初始化
*/
private static synchronized void JedisClusterInit(){
if (jedisCluster == null)
createJedisCluster();
}
/**
* 在多線程環境同步初始化
*/
private static synchronized void sentinelPoolInit(){
if (jedisSentinelPool == null)
createJedisSentinelPool();
}
/**
* 獲取一個jedis對象
* @return
*/
public static Jedis getJedis(){
if (jedisSentinelPool == null)
sentinelPoolInit();
Jedis resource = jedisSentinelPool.getResource();
// resource.auth("123");
return resource;
}
/**
* 獲取一個jedis對象
* @return
*/
public static JedisCluster getJedisCluster(){
if (jedisCluster == null)
JedisClusterInit();
return jedisCluster;
}
/**
* 釋放一個連接
* @param jedis
*/
public static void returnRes(Jedis jedis){
jedisSentinelPool.returnResource(jedis);
}
/**
* 銷燬一個連接
* @param jedis
*/
public static void returnBrokenRes(Jedis jedis){
jedisSentinelPool.returnBrokenResource(jedis);
}
/**
* 獲取集羣上所有key
* @param pattern
* @return
*/
public static TreeSet<String> keys(JedisCluster jc, String pattern){
TreeSet<String> keys = new TreeSet<>();
Map<String, JedisPool> clusterNodes = jc.getClusterNodes();
for(String k : clusterNodes.keySet()){
JedisPool jp = clusterNodes.get(k);
Jedis jedis = jp.getResource();
try {
keys.addAll(jedis.keys(pattern));
} catch(Exception e){
e.printStackTrace();
} finally{
//用完一定要close這個鏈接!!!
jedis.close();
}
}
return keys;
}
/**
* 連接redis方法
* @param args
*/
public static void main(String[] args) throws IOException {
JedisCluster jedisCluster=getJedisCluster();
/* jedisCluster.set("sjk", "hello");
jedisCluster.set("BlackChangeFlag", "false");
jedisCluster.set("ProcessChangeFlag", "false");
jedisCluster.set("FilterChangeFlag", "false");
jedisCluster.set("wh", "hello");
jedisCluster.set("lxy", "hello");
jedisCluster.set("pyx", "hello");*/
//System.out.println("sjk============" + jedisCluster.get("sjk"));
TreeSet<String> keySets = keys(jedisCluster, "CSANTI_MONITOR_DP*");
//使用完成後不要調用close,將會導致無法繼續使用該對象
//jedisCluster.close();
for(String k: keySets){
System.out.println(k + " ============ " + jedisCluster.get(k));
}
TreeSet<String> keySets1 = keys(jedisCluster, "CSANTI_MONITOR_QUERY*");
//使用完成後不要調用close,將會導致無法繼續使用該對象
//jedisCluster.close();
for(String k: keySets1){
System.out.println(k + " ------------------ " + jedisCluster.get(k));
}
TreeSet<String> keySets2 = keys(jedisCluster, "CSANTI_MONITOR_BOOK*");
//使用完成後不要調用close,將會導致無法繼續使用該對象
//jedisCluster.close();
for(String k: keySets2){
System.out.println(k + " +++++++++++++++ " + jedisCluster.get(k));
}
}
}
package com.ssq.dmp.utils.jedis;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Logger;
/**
* JedisSentinelPool連接池的方式調用redis數據庫
*
*/
public class JedisPoolUtil {
private final static Logger logger = Logger.getLogger(JedisPoolUtil.class.getName());
private static JedisSentinelPool pool = null;
public static Properties getJedisProperties() {
Properties config = new Properties();
InputStream is = null;
try {
is = JedisPoolUtil.class.getClassLoader().getResourceAsStream("config.properties");
config.load(is);
} catch (IOException e) {
logger.info(e.getMessage());
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
logger.info(e.getMessage());
}
}
}
return config;
}
/**
* 創建連接池
*
*/
private static void createJedisPool() {
// 建立連接池配置參數
JedisPoolConfig config = new JedisPoolConfig();
Properties prop = getJedisProperties();
// 設置最大連接數
config.setMaxTotal(Integer.valueOf(prop.getProperty("redis.MAX_ACTIVE")));
// 設置最大阻塞時間,記住是毫秒數milliseconds
config.setMaxWaitMillis(Integer.valueOf(prop.getProperty("redis.MAX_WAIT")));
// 設置空間連接
config.setMaxIdle(Integer.valueOf(prop.getProperty("redis.MAX_IDLE")));
// jedis實例是否可用
boolean borrow = prop.getProperty("redis.TEST_ON_BORROW") == "false" ? false : true;
config.setTestOnBorrow(borrow);
String masterName = "master001";
Set<String> sentinels = new HashSet<String>();
String serviceAddressPort1 = prop.getProperty("redis.ADRESS") + ":" + prop.getProperty("redis.PORT1");
String serviceAddressPort2 = prop.getProperty("redis.ADRESS") + ":" + prop.getProperty("redis.PORT2");
String serviceAddressPort3 = prop.getProperty("redis.ADRESS") + ":" + prop.getProperty("redis.PORT3");
sentinels.add(serviceAddressPort1);
sentinels.add(serviceAddressPort2);
sentinels.add(serviceAddressPort3);
pool = new JedisSentinelPool(masterName, sentinels, config);
}
/**
* 在多線程環境同步初始化
*/
private static synchronized void poolInit() {
if (pool == null)
createJedisPool();
}
/**
* 獲取一個jedis 對象
*
* @return
*/
public static Jedis getJedis() {
if (pool == null)
poolInit();
return pool.getResource();
}
/**
* 釋放一個連接
*
* @param jedis
*/
@SuppressWarnings("deprecation")
public static void returnRes(Jedis jedis) {
pool.returnResource(jedis);
}
/**
* 銷燬一個連接
*
* @param jedis
*/
@SuppressWarnings("deprecation")
public static void returnBrokenRes(Jedis jedis) {
pool.returnBrokenResource(jedis);
}
}
jedisConfig.properties
#jedisCluster連接配置
#redisCluster實例地址
servers = 192.168.206.178:7001,192.168.206.178:7002,192.168.206.178:7003,192.168.206.178:7004,192.168.206.178:7005,192.168.206.178:7006
#連接redisCluster實例超時時間
connectionTimeout = 300000
#讀寫redisCluster實例超時時間
soTimeout = 300000
#連接redisCluster實例重試次數
maxAttempts = 6
#jedis連接池配置
#連接池最大連接數
maxTotal = 200
#獲取連接池連接最大等待時間(毫秒)
maxWaitMillis = 15000
#最大空閒連接數
maxIdle = 50
#最小空閒連接數
minIdle = 10
#對拿到的connection進行validateObject校驗
testOnBorrow = false
#從連接池獲取不到連接則阻塞
blockWhenExhausted = true
#連接對象後進先出
lifo = true
#歸還連接到池時測試連接
testOnReturn = false
#測試連接池空閒的連接
testWhileIdle = true
#測試連接池空閒連接的時間間隔,testWhileIdle=true時生效
timeBetweenEvictionRunsMillis = 30000
#監控數據-鍵標識(分別是數據處理監控,鏈路監控,查詢監控,預訂監控)
cluster.key.monitor.dataProcess = CSANTI_MONITOR_DP
cluster.key.monitor.linkProcess = CSANTI_MONITOR_LP
cluster.key.monitor.query = CSANTI_MONITOR_QUERY
cluster.key.monitor.book = CSANTI_MONITOR_BOOK
#監控數據有效期-單位秒 86400s=24h
cluster.exptime.monitor = 86400
#反爬黑名單數據-鍵標識
cluster.key.anti_black_list = CSANTI_ANTI_BLACK
#反爬黑名單數據有效期-單位秒
cluster.exptime.anti_black_list = 3600
#反佔座黑名單數據-鍵標識
cluster.key.ocp_black_list = CSANTI_OCP_BLACK
#反佔座黑名單數據有效期-單位秒
cluster.exptime.ocp_black_list = 3600
#Mysql-黑名單是否改變標識:BlackChangeFlag(默認值false)
#Mysql-流程是否改變標識:ProcessChangeFlag(默認值false)
#Mysql-過濾規則是否改變標識:FilterChangeFlag(默認值false)
#Mysql-規則是否改變標識:AnalyzeRuleChangeFlag(默認值false)
#redis是否宕機標識(默認值no)
##以下配置爲redis單節點或主從集羣使用
#jedis連接池配置
#連接池最大連接數
#maxTotal = 200
#獲取連接池連接最大等待時間(毫秒)
#maxWaitMillis = 15000
#最大空閒連接數
#maxIdle = 50
#最小空閒連接數
#minIdle = 10
#對拿到的connection進行validateObject校驗
#testOnBorrow = false
#從連接池獲取不到連接則阻塞
#blockWhenExhausted = true
#連接對象後進先出
#lifo = true
#歸還連接到池時測試連接
#testOnReturn = false
#測試連接池空閒的連接
#testWhileIdle = true
#測試連接池空閒連接的時間間隔,testWhileIdle=true時生效
#timeBetweenEvictionRunsMillis = 30000
#哨兵模式中的主機名
#MASTER = master001
#主從機地址+端口號
#SENTINEL_1 = 192.168.30.161:26381
#SENTINEL_2 = 192.168.30.161:26382
#SENTINEL_3 = 192.168.30.161:26383
#庫序號-監控數據庫
#db.index.monitor = 0
#監控數據庫-監控數據有效期-單位秒
#db.exptime.monitor = 3600
#庫序號-反爬結果黑名單數據庫
#db.index.anti_black_list = 5
#反爬庫-黑名單有效期-單位秒
#db.exptime.anti_black_list = 3600
#庫序號-mysql配置項數據更新標識數據庫
#db.index.configuration_change = 2
#庫序號-保存流量總和,用於前端顯示(僅前端使用)
#db.index.flow_data_sum = 7
注意
原因:我們使用的是redis3.0的集羣,用jedis的JedisCluster.close()方法造成的集羣連接關閉的情況。 jedisCluster內部使用了池化技術,每次使用完畢都會自動釋放Jedis因此不需要關閉
單機模式
單機模式需要手動close
package com.ssq.dmp.utils
import redis.clients.jedis.{Jedis, JedisPool, JedisPoolConfig}
object JedisConnectionPool{
val conf = new JedisPoolConfig()
//最大連接數,
conf.setMaxTotal(20)
//最大空閒連接數
conf.setMaxIdle(10)
//當調用borrow Object方法時,是否進行有效性檢查 -->
conf.setTestOnBorrow(true)
//10000代表超時時間(10秒)
val pool = new JedisPool(conf, "slave2", 6379, 10000)
def getConnection(): Jedis = {
pool.getResource
}
def main(args: Array[String]): Unit = {
val jedis = getConnection()
println(jedis.get("sss"))
}
}