成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

你知道 Redis 使用的什么協(xié)議嗎?

存儲 存儲軟件 Redis
先從持久化說起,雖然一提到 Redis,首先想到的就是緩存,但是 Redis 不僅僅是緩存這么簡單,它的定位是內(nèi)存型數(shù)據(jù)庫,可以存儲多種類型的數(shù)據(jù)結(jié)構(gòu),還可以當做簡單消息隊列使用。既然是數(shù)據(jù)庫,持久化功能是必不可少的。

[[353629]]

有個小伙伴面試回來說面試官問了他一些 Redis 問題,但是他好像沒有回答上來。

我說,你 Redis 不是用的很溜嗎,什么問題難住你了。

他說,事情是這樣的,剛開始,問了一些基礎(chǔ)的問題,比如 Redis 的幾種基本數(shù)據(jù)類型和使用場景,以及主從復制和集群的一些問題,這些都還好。

然后問 Redis 的兩種持久化方式,他說與 RDB 和 AOF 兩種方式,RDB 數(shù)據(jù)文件小,恢復速度快,但是對性能有影響,而且不適合實時存儲。而 AOF 是現(xiàn)在最常用的持久化方式,它的一大優(yōu)點就是實時性,并且對 Redis 半身性能影響最小。

那面試又問了,你知道 AOF 持久化之后的文件是什么格式嗎?

答:好像就是文本文件吧?

好,文本文件,那你知道它有什么規(guī)則嗎?或者說,它和 Redis 的協(xié)議有什么關(guān)系嗎?

答:啊,這個,恩,不太清楚呢。

現(xiàn)在就來看一下 AOF 和 RESP 協(xié)議的關(guān)系

  1. 從兩種持久化方式說起。
  2. RESP 協(xié)議是什么
  3. 動手實現(xiàn)一個簡單的協(xié)議解析命令行工具

 

先從持久化說起,雖然一提到 Redis,首先想到的就是緩存,但是 Redis 不僅僅是緩存這么簡單,它的定位是內(nèi)存型數(shù)據(jù)庫,可以存儲多種類型的數(shù)據(jù)結(jié)構(gòu),還可以當做簡單消息隊列使用。既然是數(shù)據(jù)庫,持久化功能是必不可少的。

Redis 的兩種持久化方式

Redis 提供了兩種持久化方式,一種是 RDB 方式,另外一種是 AOF 方式,AOF 是目前比較流行的持久化方案。

RDB 方式

RDB持久化是通過快照的方式,在指定的時間間隔內(nèi)將內(nèi)存中的數(shù)據(jù)集快照寫入磁盤。它以一種緊湊壓縮的二進制文件的形式出現(xiàn)。可以將快照復制到其他服務(wù)器以創(chuàng)建相同數(shù)據(jù)的服務(wù)器副本,或者在重啟服務(wù)器后恢復數(shù)據(jù)。RDB是Redis默認的持久化方式,也是早期版本的必須方案。

RDB 由下面幾個參數(shù)控制。

  1. # 設(shè)置 dump 的文件名 
  2. dbfilename dump.rdb 
  3.  
  4. # 持久化文件的存儲目錄 
  5. dir ./ 
  6.  
  7. # 900秒內(nèi),如果至少有1個key發(fā)生變化,就會自動觸發(fā)bgsave命令創(chuàng)建快照 
  8. save 900 1 
  9.  
  10. # 300秒內(nèi),如果至少有10個key發(fā)生變化,就會自動觸發(fā)bgsave命令創(chuàng)建快照 
  11. save 300 10 
  12.  
  13. # 60秒內(nèi),如果至少有10000個key發(fā)生變化,就會自動觸發(fā)bgsave命令創(chuàng)建快照 
  14. save 60 10000 

持久化流程

上面說到了配置文件中的幾個觸發(fā)持久化的機制,比如 900 秒、300秒、60秒,當然也可以手動執(zhí)行命令 save或bgsave進行觸發(fā)。bgsave是非阻塞版本,通過 fork 出子進程的方式來進行快照生成,而 save會阻塞主進程,不建議使用。

1、首先 bgsave命令觸發(fā);

2、父進程 fork 出一個子進程,這一步是比較重量級的操作,也是 RDB 方式性能不及 AOF 的一個重要原因;

3、父進程 fork 出子進程后就可以正常的相應(yīng)客戶端發(fā)來的其他命令了;

4、子進程開始進行持久化工作,對現(xiàn)有數(shù)據(jù)進行完整的快照存儲;

5、子進程完成操作后,通知父進程;

 

RDB的優(yōu)點:

  • RDB是一個緊湊壓縮的二進制文件,代表Redis在某個時間點上的數(shù)據(jù) 快照。非常適用于備份,全量復制等場景。比如每6小時執(zhí)行bgsave備份, 并把RDB文件拷貝到遠程機器或者文件系統(tǒng)中(如hdfs),用于災(zāi)難恢復。
  • Redis加載RDB恢復數(shù)據(jù)遠遠快于AOF的方式。

RDB的缺點:

  • RDB方式數(shù)據(jù)沒辦法做到實時持久化/秒級持久化。因為bgsave每次運 行都要執(zhí)行fork操作創(chuàng)建子進程,屬于重量級操作,頻繁執(zhí)行成本過高。
  • RDB文件使用特定二進制格式保存,Redis版本演進過程中有多個格式 的RDB版本,存在老版本Redis服務(wù)無法兼容新版RDB格式的問題。

AOF 方式

AOF 由下面幾個參數(shù)控制。

  1. # appendonly參數(shù)開啟AOF持久化 
  2. appendonly yes 
  3.  
  4. # AOF持久化的文件名,默認是appendonly.aof 
  5. appendfilename "appendonly.aof" 
  6.  
  7. # AOF文件的保存位置和RDB文件的位置相同,都是通過dir參數(shù)設(shè)置的 
  8. dir ./ 
  9.  
  10. # 同步策略 
  11. # appendfsync always 
  12. appendfsync everysec 
  13. # appendfsync no 
  14.  
  15. # aof重寫期間是否同步 
  16. no-appendfsync-on-rewrite no 
  17.  
  18. # 重寫觸發(fā)配置 
  19. auto-aof-rewrite-percentage 100 
  20. auto-aof-rewrite-min-size 64mb 
  21.  
  22. # 加載aof出錯如何處理 
  23. aof-load-truncated yes 
  24.  
  25. # 文件重寫策略 
  26. aof-rewrite-incremental-fsync yes 

針對RDB不適合實時持久化的問題,Redis提供了AOF 持久化方式來解決,AOF 也是目前最流程的持久化方式。

AOF(append only file),以獨立日志的方式記錄每次寫命令, 重啟時再重新執(zhí)行AOF文件中的命令達到恢復數(shù)據(jù)的目的。

1、所有的寫入命令會追加到aof_buf(緩沖區(qū))中;

2、AOF緩沖區(qū)根據(jù)對應(yīng)的策略向硬盤做同步操作;

3、隨著AOF文件越來越大,需要定期對AOF文件進行重寫,達到壓縮的目的;

4、當Redis服務(wù)器重啟時,可以加載AOF文件進行數(shù)據(jù)恢復;

 

AOF 文件里存的是什么

我在本地的測試 redis 環(huán)境中隨便刷了幾條命令,然后打開 appendonly.aof 文件查看,發(fā)現(xiàn)里面的內(nèi)容像下面這樣子。

 

RESP 協(xié)議Redis客戶端與服務(wù)端通信,使用 RESP 協(xié)議通信,該協(xié)議是專門為 Redis 設(shè)計的通信協(xié)議,但也可以用于其它客戶端-服務(wù)器通信的場景。

RESP 協(xié)議

有如下幾個特點:

  • 實現(xiàn)簡單;
  • 快速解析;
  • 可閱讀;

客戶端發(fā)送命令給服務(wù)端,服務(wù)端拿到命令后進行解析,然后執(zhí)行對應(yīng)的邏輯,之后返回給客戶端,當然了,這一發(fā)一回復都是用的 RESP 協(xié)議特點的格式。

一般情況下我們會使用 redis-cli或者一些客戶端工具連接 Redis 服務(wù)端。

  1. ./redis-cli 

然后整個交互過程的命令發(fā)送和返回結(jié)果像下面這樣,綠色部分為發(fā)送的命令,紅色部分為返回的結(jié)果。

 

這就是我們再熟悉不過的部分了。但是,這并不能看出 RESP 協(xié)議的真實面貌。

用 telnet 試試

RESP 是基于 TCP 協(xié)議實現(xiàn)的,所以除了用各種客戶端工具以及 Redis 提供的 redis-cli工具,還可以用 telnet 查看,用 telnet 就可以看出 RESP 返回的原始數(shù)據(jù)格式了。

我本地的 Redis 是用的默認 6379 端口,并且沒有設(shè)置 requirepass ,我們來試一下用 telnet 連接。

  1. telnet 127.0.0.1 6379 

然后執(zhí)行與前面相同的幾條命令,發(fā)送和返回的結(jié)果如下,綠色部分為發(fā)送的命令,紅色為返回的結(jié)果。

 

怎么樣,有些命令的返回還好,但是像get str:hello這條,返回的結(jié)果除了 world值本身,上面還多了一行 $5,是不是有點迷糊了。

協(xié)議規(guī)則

請求命令

一條客戶端發(fā)往服務(wù)器的命令的規(guī)則如下:

  1. *<參數(shù)數(shù)量> CR LF 
  2. $<參數(shù) 1 的字節(jié)數(shù)量> CR LF 
  3. <參數(shù) 1 的數(shù)據(jù)> CR LF 
  4. ... 
  5. $<參數(shù) N 的字節(jié)數(shù)量> CR LF 
  6. <參數(shù) N 的數(shù)據(jù)> CR LF 

RESP 用\r\n作為分隔符,會表明此條命令的具體參數(shù)個數(shù),在命令上看來,空格分隔的都表示一個參數(shù),例如 set str:hello world 這條命令就是3個參數(shù),會表明每個參數(shù)的字符數(shù)和具體內(nèi)容。

用這條命令舉例,對應(yīng)到 RESP 協(xié)議規(guī)則上就會變成下面這個樣子:

  1. *3\r\n$3\r\nset\r\n$9str:hello\r\n$5world\r\n 

 

服務(wù)端回復

Redis 命令會返回多種不同類型的回復。

通過檢查服務(wù)器發(fā)回數(shù)據(jù)的第一個字節(jié), 可以確定這個回復是什么類型:

1、狀態(tài)回復(status reply)的第一個字節(jié)是 "+"

比如 ping命令的回復,+PONG\r\n

2、錯誤回復(error reply)的第一個字節(jié)是 "-"

比如輸入一個 redis 中不存在的命令,或者給某些命令設(shè)置錯誤的參數(shù),例如輸入auth,auth 命令后面需要有一個密碼參數(shù)的,如果不輸入就會返回錯誤回復類型。

-ERR wrong number of arguments for 'auth' command\r\n

3、整數(shù)回復(integer reply)的第一個字節(jié)是 ":"

例如 INCR、DECR 自增自減命令,返回的結(jié)果是這樣的 :2\r\n

4、批量回復(bulk reply)的第一個字節(jié)是 "$"

例如對 string 類型執(zhí)行 get 操作,$5\r\nworld\r\n,$后面的數(shù)字 5 表示返回的結(jié)果有 5 個字符,后面是返回結(jié)果的實際內(nèi)容。

5、多條批量回復(multi bulk reply)的第一個字節(jié)是 "*"

例如 LRANGE key start stop或者 hgetall等返回多條結(jié)果的命令,比如 lrange命令返回的結(jié)果:

  1. *2\r\n$6\r\nnews-2\r\n$6\r\nnews-1\r\n 

多條批量回復和前面說的客戶端發(fā)送命令的格式是一致的。

實現(xiàn)一個簡單的 Redis 交互工具

了解了 Redis 的協(xié)議規(guī)則,我們就可以自己寫一個簡單的客戶端了。當然,通過官網(wǎng)我們可以看到已經(jīng)有各種語言,而且每種語言有不止一個客戶端工具了。

 

比如 Java 語言的客戶端就有這么多種,其中 Jedis 應(yīng)該是用的最多了,既然已經(jīng)有這么好用的輪子了,當然沒必要重復造輪子,主要還是為了加深印象。

 

RESP 協(xié)議基于 TCP 協(xié)議,可以使用 socket 方式進行連接。

  1. public Socket createSocket() throws IOException { 
  2.   Socket socket = null
  3.   try { 
  4.     socket = new Socket(); 
  5.     socket.setReuseAddress(true); 
  6.     socket.setKeepAlive(true); 
  7.     socket.setTcpNoDelay(true); 
  8.     socket.setSoLinger(true, 0); 
  9.  
  10.     socket.connect(new InetSocketAddress(host, port), DEFAULT_TIMEOUT); 
  11.     socket.setSoTimeout(DEFAULT_TIMEOUT); 
  12.     outputStream = socket.getOutputStream(); 
  13.     inputStream = socket.getInputStream(); 
  14.     return socket; 
  15.   } catch (Exception ex) { 
  16.     if (socket != null) { 
  17.       socket.close(); 
  18.     } 
  19.     throw ex; 
  20.   } 

然后剩下的就是對返回的結(jié)果進行字符串的解析了,我做的工具就到簡陋的到這一步了,下面是一些簡單命令的返回輸出。

 

代碼已放到 github 上,有興趣的可以 clone 下來看一下。

https://github.com/huzhicheng/medis

本文轉(zhuǎn)載自微信公眾號「 古時的風箏」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系 古時的風箏公眾號。

 

責任編輯:武曉燕 來源: 古時的風箏
相關(guān)推薦

2024-01-15 12:16:37

2010-09-17 15:32:09

Linux網(wǎng)絡(luò)協(xié)議棧

2020-02-20 08:30:49

OSPF網(wǎng)絡(luò)協(xié)議路由協(xié)議

2014-08-21 10:27:58

創(chuàng)業(yè)初創(chuàng)技術(shù)

2017-10-16 13:45:04

2021-08-29 18:01:57

HTTP協(xié)議版本

2023-11-06 18:33:19

分庫分表數(shù)據(jù)庫

2022-09-28 18:16:34

JavaJDK

2019-05-30 22:27:51

云計算成本云服務(wù)

2023-06-30 08:26:24

Java注解Java程序元素

2021-11-12 05:59:23

容災(zāi)備份5G

2015-12-01 13:33:51

UnikernelLinux運維

2023-12-20 08:23:53

NIO組件非阻塞

2024-04-30 09:02:48

2020-10-08 18:58:46

條件變量開發(fā)線程

2023-10-16 23:12:02

Redis數(shù)據(jù)結(jié)構(gòu)

2019-08-16 09:07:47

RedisNoSQL數(shù)據(jù)庫

2025-02-18 08:11:17

2022-11-28 00:04:17

2016-09-29 15:43:33

點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产精品一区二区在线 | 久久久av一区 | 综合色在线 | aa级毛片毛片免费观看久 | 成人免费毛片片v | 神马影院一区二区三区 | 精品一区二区三区免费视频 | www.精品一区 | 91精品国产综合久久久动漫日韩 | 大学生a级毛片免费视频 | 国产欧美一级二级三级在线视频 | 国产免费麻豆视频 | 亚洲av一级毛片 | 欧美日韩国产一区二区三区不卡 | 亚洲天堂中文字幕 | 精品国产视频 | 欧美国产视频 | 99热精品6 | 久久99深爱久久99精品 | 成人亚洲片 | 久久精品国产一区 | 国产激情视频在线观看 | 日韩av.com | 国产一级视频 | 亚欧洲精品在线视频免费观看 | 欧美综合久久久 | 国产综合视频 | 欧美在线视频一区二区 | 国产欧美视频一区二区 | 欧美成人精品欧美一级 | av在线成人 | 美女张开腿露出尿口 | 亚洲欧美中文日韩在线 | 国产欧美精品在线观看 | 一级片毛片| 久久香焦 | 亚洲天堂av在线 | 一区二区三区免费网站 | 精品视频一区二区在线观看 | 在线观看久草 | 午夜爽爽爽男女免费观看影院 |