Jedis介紹及常見問題分析

白宸發表於2017-04-20

Jedis介紹

Jedis是一個開源的Redis資料庫客戶端,相容Redis 2.8.x和3.xx,Jedis提供了以下特性:

  • 排序
  • 連結管理
  • 不同型別的value的命令處理
  • String型別的命令處理
  • Hashes型別的命令處理
  • Lists型別的命令處理
  • Sets型別的命令處理
  • Sorted Sets型別的命令處理
  • 事務
  • 批量命令處理
  • 訂閱/釋出
  • 持久化的控制命令
  • 遠端控制命令
  • 分片(MD5,MurmurHash)
  • 叢集的Key-tags功能
  • 叢集的批量命令處理
  • 指令碼的批量命令處理
  • Redis叢集支援

如何使用

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
    <type>jar</type>
    <scope>compile</scope>
</dependency>

直連模式

import redis.clients.jedis.Jedis;
public class jedistest {
public static void main(String[] args) {
    try {
        String host = "xx.kvstore.aliyuncs.com";//控制檯顯示訪問地址
        int port = 6379;
        Jedis jedis = new Jedis(host, port);
        //鑑權資訊
        jedis.auth("password");//password
        String key = "redis";
        String value = "aliyun-redis";
        //select db預設為0
        jedis.select(1);
        //set一個key
        jedis.set(key, value);
        System.out.println("Set Key " + key + " Value: " + value);
        //get 設定進去的key
        String getvalue = jedis.get(key);
        System.out.println("Get Key " + key + " ReturnValue: " + getvalue);
        jedis.quit();
        jedis.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
}

連線池模式

JedisPoolConfig config = new JedisPoolConfig();
//最大空閒連線數, 應用自己評估,不要超過ApsaraDB for Redis每個例項最大的連線數
config.setMaxIdle(200);
//最大連線數, 應用自己評估,不要超過ApsaraDB for Redis每個例項最大的連線數
config.setMaxTotal(300);
config.setTestOnBorrow(false);
config.setTestOnReturn(false);
String host = "*.aliyuncs.com";
String password = "密碼";
JedisPool pool = new JedisPool(config, host, 6379, 3000, password);
Jedis jedis = null;
try {
    jedis = pool.getResource();
    /// ... do stuff here ... for example
    jedis.set("foo", "bar");
    String foobar = jedis.get("foo");
    jedis.zadd("sose", 0, "car");
    jedis.zadd("sose", 0, "bike");
    Set<String> sose = jedis.zrange("sose", 0, -1);
} finally {
    if (jedis != null) {
        jedis.close();
    }
}
/// ... when closing your application:
pool.destroy();

常見出錯問題排查

連線池錯誤

使用Jedis連線池模式的時候容易出現的錯誤是無法獲取連線池

redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

對於這類問題的原因有幾類,可以根據以下一一進行排查

網路檢查

首先檢查是否網路問題,可以通過telnet host 6379進行簡單測試,連上之後auth 密碼回車檢視是否返回+OKrn,如果能夠正確返回繼續檢查ping請求或者讀寫請求是否正常返回,操作多次排查網路問題影響。

JedisPool連線數設定檢查

JedisPool使用的時候需要進行連線池的設定,使用者在超過MaxTotal連線數的時候也會出現獲取不到連線池的情況,這個時候可以在訪問客戶端上通過netstat -an | grep 6379 | grep EST | wc -l 檢視連結的客戶端連結數目,並且比較這個數目和JedisPool配置的MaxTotal的值,如果沒有明顯超過或者接近就可以排除JedisPool連線池配置的影響。

JedisPool連線池程式碼檢查

對於JedisPool連線池的操作,每次getResource之後需要呼叫returnResource或者close進行歸還,可以檢視程式碼是否有正確使用,程式碼sample可以參考上面的

檢查是否發生nf_conntrack丟包

通過dmesg檢查客戶端是否有異常

nf_conntrack: table full, dropping packet

如果發生nf_conntract丟包可以通過修改設定sysctl -w net.netfilter.nf_conntrack_max=120000

檢查是否TIME_WAIT問題

通過ss -s 檢視time wait連結是否過多
screenshot.png
如果TIME_WAIT過多可以修改以下引數

sysctl -w net.ipv4.tcp_max_tw_buckets=180000
sysctl -w net.ipv4.tcp_tw_recycle=1

檢查是否DNS問題

通過在/etc/hosts檔案直接繫結host地址,繫結完成之後檢視問題是否還存在,如果還存在則不是DNS解析問題

192.168.1.1  *.redis.rds.aliyuncs.com

總結

如果按照上面排查之後還有問題可以通過抓包並將報錯時間點,報錯資訊,抓包檔案傳送給阿里雲售後同學進行分析。抓包命令為sudo tcpdump -i eth0 tcp and port 6379 -n -nn -s 74 -w redis.cap。


相關文章