1. 程式人生 > >對Redis的深入理解與解析

對Redis的深入理解與解析

最近換了專案中,突然碰到redis了,對他的理解很有限,這裡做個分享。

1.Redis的連線池(JedisPool)

說到連線池,我的第一反應是這可能跟資料來源的C3P0類似。結果一查,恩,差不多。

Redis是一種C/S的模式,但是頻繁的連結會導致花費在底層連結上的時間大大增加(因為Redis是基於記憶體的,讀取效率高,假設一次資料互動總共用時30ms,超高效能的Redis資料庫處理資料所花的時間可能不到1ms,也即是說前期的連線佔用了29ms)。顯然很不合理,怎麼辦呢。於是JedisPool就開始出現了。

連線池可以使在客戶端建立多個連線並且不釋放,想連結即可通過某演算法建立連線,用完了,歸還即可。這就免去了資料庫連結所需要的時間。

但是如果超過連線池的上限以後,會怎麼樣呢:採用IO的多路複用來解決。

2.連線池的配置

package com.jedis;

import java.util.concurrent.locks.ReentrantLock;  
import org.apache.commons.lang.StringUtils;  
import org.apache.log4j.Logger;
import org.junit.Test;

import redis.clients.jedis.Jedis;  
import redis.clients.jedis.JedisPool;  
import redis.clients.jedis.JedisPoolConfig;  
  
/**
 * Reids的工具類  
 * @author EdwardShen
 *
 * 2018年4月30日
 */
public class JedisUtil {  
  
    protected static ReentrantLock lockPool = new ReentrantLock();  
    protected static ReentrantLock lockJedis = new ReentrantLock();  
  
    protected static Logger logger = Logger.getLogger(JedisUtil.class);  
  
    //Redis伺服器IP  
    private static String ADDR_ARRAY = "127.0.0.1,127.0.0.2";  
  
    //Redis的埠號  
    private static int PORT = 6379;  
  
    //訪問密碼  
    private static String AUTH = "http://blog.csdn.net/sx1119183530";  
    //可用連線例項的最大數目,預設值為8;  
    //如果賦值為-1,則表示不限制;如果pool已經分配了maxActive個jedis例項,則此時pool的狀態為exhausted(耗盡)。  
    private static int MAX_ACTIVE = 8;  
  
    //控制一個pool最多有多少個狀態為idle(空閒的)的jedis例項,預設值也是8。  
    private static int MAX_IDLE = 8;  
  
    //等待可用連線的最大時間,單位毫秒,預設值為-1,表示永不超時。如果超過等待時間,則直接丟擲JedisConnectionException;  
    private static int MAX_WAIT = 3000;  
  
    //超時時間  
    private static int TIMEOUT = 10000;  
  
    //在borrow一個jedis例項時,是否提前進行validate操作;如果為true,則得到的jedis例項均是可用的;  
    private static boolean TEST_ON_BORROW = false;  
  
    private static JedisPool jedisPool = null;  
  
    /** 
     * redis過期時間,以秒為單位 
     */  
    public final static int EXRP_HOUR = 60 * 60;            //一小時  
    public final static int EXRP_DAY = 60 * 60 * 24;        //一天  
    public final static int EXRP_MONTH = 60 * 60 * 24 * 30; //一個月  
  
    /** 
     * 初始化Redis連線池 
     */  
    @Test
    private static void initialPool() {  
        try {  
            JedisPoolConfig config = new JedisPoolConfig();  
            config.setMaxTotal(MAX_ACTIVE);  
            config.setMaxIdle(MAX_IDLE);  
            config.setMaxWaitMillis(MAX_WAIT);  
            config.setTestOnBorrow(TEST_ON_BORROW);  
            System.out.println(ADDR_ARRAY.split(",")[0]+":"+ADDR_ARRAY.split(",")[1]);
            jedisPool = new JedisPool(config, ADDR_ARRAY.split(",")[0], PORT, TIMEOUT, AUTH);  
        } catch (Exception e) {  
            logger.error("First create JedisPool error : " + e);  
            try {  
                //如果第一個IP異常,則訪問第二個IP  
                JedisPoolConfig config = new JedisPoolConfig();  
                config.setMaxTotal(MAX_ACTIVE);  
                config.setMaxIdle(MAX_IDLE);  
                config.setMaxWaitMillis(MAX_WAIT);  
                config.setTestOnBorrow(TEST_ON_BORROW);  
                jedisPool = new JedisPool(config, ADDR_ARRAY.split(",")[1], PORT, TIMEOUT, AUTH);  
            } catch (Exception e2) {  
                logger.error("Second create JedisPool error : " + e2);  
            }  
        }  
    }  
  
    /** 
     * 在多執行緒環境同步初始化 
     */  
    private static void poolInit() {  
        lockPool.lock();  
        try {  
            if (jedisPool == null) {  
                initialPool();  
            }  
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            lockPool.unlock();  
        }  
    }  
  
    public static Jedis getJedis() {  
        lockJedis.lock();  
        if (jedisPool == null) {  
            poolInit();  
        }  
        Jedis jedis = null;  
        try {  
            if (jedisPool != null) {  
                jedis = jedisPool.getResource();  
            }  
        } catch (Exception e) {  
            logger.error("Get jedis error : " + e);  
        } finally {  
            returnResource(jedis);  
            lockJedis.unlock();  
        }  
        return jedis;  
    }  
  
    /** 
     * 釋放jedis資源 
     * 
     * @param jedis 
     */  
    public static void returnResource(final Jedis jedis) {  
        if (jedis != null && jedisPool != null) {  
            jedisPool.returnResource(jedis);  
        }  
    }  
  
    /** 
     * 設定 String 
     * 
     * @param key 
     * @param value 
     */  
    public synchronized static void setString(String key, String value) {  
        try {  
            value = StringUtils.isEmpty(value) ? "" : value;  
            getJedis().set(key, value);  
        } catch (Exception e) {  
            logger.error("Set key error : " + e);  
        }  
    }  
  
    /** 
     * 設定 過期時間 
     * 
     * @param key 
     * @param seconds 以秒為單位 
     * @param value 
     */  
    public synchronized static void setString(String key, int seconds, String value) {  
        try {  
            value = StringUtils.isEmpty(value) ? "" : value;  
            getJedis().setex(key, seconds, value);  
        } catch (Exception e) {  
            logger.error("Set keyex error : " + e);  
        }  
    }  
  
    /** 
     * 獲取String值 
     * 
     * @param key 
     * @return value 
     */  
    public synchronized static String getString(String key) {  
        if (getJedis() == null || !getJedis().exists(key)) {  
            return null;  
        }  
        return getJedis().get(key);  
    }  
}  

測試類:

package com.jedis;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.junit.Test;
/**
 * 測試類
 * @author EdwardShen
 *
 * 2018年4月30日
 */
public class TestJedis extends Thread {
	int i = 0;

	public  TestJedis(int i) {
		this.i = i;
	}

	public void run() {
		Date date = new Date();
		DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String time = format.format(date);
		JedisUtil.setString("foo", time);
		String foo = JedisUtil.getString("foo");
		System.out.println("【輸出>>>>】foo:" + foo + " 第:" + i + "個執行緒" + "當前時間:" + format.format(new Date()));
	}
	
	
	@Test
	public void test()
	{
		System.out.println("kaishil  !");
		 for (int i = 0; i < 10000; i++) {            
			 TestJedis t = new TestJedis(i);  
	            t.start();  
	        } 
	}
}