你不知道的redis四-redis執行原理

2020-09-24 15:01:24

目錄

一、Redis執行原理

 二、redis執行協定 

RESP協定

模擬resp協定進行redis寫入

三、redis效能測試

Redis慢查詢分析

Redis慢查詢極值設定

慢查詢原理

慢查詢命令


一、Redis執行原理

redis伺服器對命令的處理都是單執行緒的,但是I/O層面卻面向多個使用者端並行地提供服務,並行到內部單執行緒的轉化通過多路複用框架來實現。redis命令從傳送到執行經理以下四個過程

  1. 傳送命令
  2. 命令排隊
  3. 命令執行
  4. 結果返回

 二、redis執行協定 

對redis請求進行抓包,檢視抓包內容

1、執行抓包命令

2、檢視抓包內容 

redis協定位於TCP層之上,即使用者端和redis範例保持雙工的連線,互動的都是序列化後的協定資料

RESP協定

Redis 伺服器與使用者端通過RESP(REdis Serialization Protocol)協定通訊。

RESP 底層採用的是TCP 的連線方式,通過tcp 進行資料傳輸,然後根據解析規則解析相應資訊,完成互動。

我們可以測試下,首先執行一個serverSocket 監聽6379,來接收redis 使用者端的請求資訊。實現如下

1、建立socket連線監聽6379埠,用於接收請求並輸出

/**
 * /**
 * <p>模擬redis</p>
 *
 * @author DK
 * @version V1.0
 */
public class SimulatedRedis {

    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(6379);
        Socket rec = server.accept();
        byte[] result = new byte[2048];
        rec.getInputStream().read(result);
        System.out.println(new String(result));
    }
}

2、使用jedis客戶度端請求本地6379埠

/**
 * /**
 * <p>模擬redis</p>
 *
 * @author DK 
 * @version V1.0
 */
public class SimulatedRedisClient {

    public static void main(String[] args) throws IOException {
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        jedis.set("user:2", "9999");
        jedis.close();
    }
} 

 列印輸出

發現和抓包內容一致

每個欄位標示含義為:

*3    表示有幾組資料 

$ 3   表示set長度為3

Set   命令

$6    表示key長度為6

User:2   key

$1    表示value長度為1

 2       value

主要以下特點:從上述範例中發現,redis使用resp協定的好處為容易實現,解析快,人類可讀,並且傳輸在TCP層,可以減少不必要的資訊傳輸

模擬resp協定進行redis寫入

/**
 * /**
 * <p>模擬redis</p>
 *
 * @author DK 
 * @version V1.0
 */
public class RespRedis {

    public static void main(String[] args) {
        SocketAddress addr = new InetSocketAddress("10.1.253.188", 6379);
        Socket sk = new Socket();
        try {
            sk.connect(addr);
            OutputStream out = sk.getOutputStream();
            StringBuffer sb = new StringBuffer();
            sb.append("*3\r\n");
            sb.append("$3\r\n");
            sb.append("SET\r\n");
            sb.append("$6\r\n");
            sb.append("user:0\r\n");
            sb.append("$5\r\n");
            sb.append("11111\r\n");
            System.out.println(sb.toString());
            byte[] b = sb.toString().getBytes();
            out.write(b);
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

三、redis效能測試

Redis慢查詢分析

mysql一樣:當執行時間超過極大值時,會將發生時間 耗時 命令記錄

redis命令生命週期:傳送 排隊 執行 返回,慢查詢只統計3執行步驟的時間

Redis慢查詢極值設定

一般有兩種方式,預設時間為10ms

1、命令方式

config set slowlog-log-slower-than 10000  //10毫秒

使用config set完後,若想將設定持久化儲存到redis.conf,要執行config rewrite

2、組態檔修改

redis.conf修改:找到slowlog-log-slower-than 10000 ,修改儲存即可

注意:slowlog-log-slower-than =0記錄所有命令 -1命令都不記錄

慢查詢原理

慢查詢記錄也是存在佇列裡的,slow-max-len 存放的記錄最大條數,

比如設定的slow-max-len=10,當有第11條慢查詢命令插入時,佇列的第一條命令

就會出列,第11條入列到慢查詢佇列中, 可以config set動態設定,

也可以修改redis.conf完成設定

慢查詢命令

獲取佇列裡慢查詢的命令:slowlog get

獲取慢查詢列表當前的長度:slowlog len    //以上只有1條慢查詢,返回1;

1)對慢查詢列表清理(重置):slowlog reset //再查slowlog len 此時返回0 清空;

2)對於線上slow-max-len設定的建議:線上可加大slow-max-len的值,記錄慢查詢存長命令時redis會做截斷,不會佔用大量記憶體,線上可設定1000以上

3)對於線上slowlog-log-slower-than設定的建議:預設為10毫秒,根據redis並行量來調整,對於高並行比建議為1毫秒

4)慢查詢是先進先出的佇列,存取紀錄檔記錄出列丟失,需定期執行slowlog get,將結果儲存到其它裝置中(如mysql)

1、redis-benchmark -h 127.0.0.1 -p 6379 -c 100 -n 10000

     100個並行連線,10000個請求,檢測伺服器效能