<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 4715字,需瀏覽 10分鐘

           ·

          2021-01-04 21:09

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

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

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

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

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

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

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

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

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

          1. 從兩種持久化方式說起。

          2. RESP 協(xié)議是什么

          3. 動手實(shí)現(xiàn)一個簡單的協(xié)議解析命令行工具



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

          ?

          Redis 的兩種持久化方式

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

          RDB 方式

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

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

          #?設(shè)置?dump?的文件名
          dbfilename?dump.rdb

          #
          ?持久化文件的存儲目錄
          dir?./

          #
          ?900秒內(nèi),如果至少有1個key發(fā)生變化,就會自動觸發(fā)bgsave命令創(chuàng)建快照
          save?900?1

          #
          ?300秒內(nèi),如果至少有10個key發(fā)生變化,就會自動觸發(fā)bgsave命令創(chuàng)建快照
          save?300?10

          #
          ?60秒內(nèi),如果至少有10000個key發(fā)生變化,就會自動觸發(fā)bgsave命令創(chuàng)建快照
          save?60?10000

          持久化流程

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

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

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

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

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

          5、子進(jìn)程完成操作后,通知父進(jìn)程;


          RDB的優(yōu)點(diǎn):

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

          RDB的缺點(diǎn):

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

          AOF 方式

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

          #?appendonly參數(shù)開啟AOF持久化
          appendonly?yes

          #
          ?AOF持久化的文件名,默認(rèn)是appendonly.aof
          appendfilename?"appendonly.aof"

          #
          ?AOF文件的保存位置和RDB文件的位置相同,都是通過dir參數(shù)設(shè)置的
          dir?./

          #
          ?同步策略
          #?appendfsync?always
          appendfsync?everysec
          #?appendfsync?no

          #
          ?aof重寫期間是否同步
          no-appendfsync-on-rewrite?no

          #
          ?重寫觸發(fā)配置
          auto-aof-rewrite-percentage?100
          auto-aof-rewrite-min-size?64mb

          #
          ?加載aof出錯如何處理
          aof-load-truncated?yes

          #
          ?文件重寫策略
          aof-rewrite-incremental-fsync?yes

          針對RDB不適合實(shí)時持久化的問題,Redis提供了AOF 持久化方式來解決,AOF 也是目前最流程的持久化方式。
          AOF(append only file),以獨(dú)立日志的方式記錄每次寫命令, 重啟時再重新執(zhí)行AOF文件中的命令達(dá)到恢復(fù)數(shù)據(jù)的目的。
          1、所有的寫入命令會追加到aof_buf(緩沖區(qū))中;
          2、AOF緩沖區(qū)根據(jù)對應(yīng)的策略向硬盤做同步操作;
          3、隨著AOF文件越來越大,需要定期對AOF文件進(jìn)行重寫,達(dá)到壓縮的目的;
          4、當(dāng)Redis服務(wù)器重啟時,可以加載AOF文件進(jìn)行數(shù)據(jù)恢復(fù);

          AOF 文件里存的是什么

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

          ?

          ?

          RESP 協(xié)議

          Redis客戶端與服務(wù)端通信,使用 RESP 協(xié)議通信,該協(xié)議是專門為 Redis 設(shè)計的通信協(xié)議,但也可以用于其它客戶端-服務(wù)器通信的場景。
          RESP 協(xié)議有如下幾個特點(diǎn):
          • 實(shí)現(xiàn)簡單;
          • 快速解析;
          • 可閱讀;
          客戶端發(fā)送命令給服務(wù)端,服務(wù)端拿到命令后進(jìn)行解析,然后執(zhí)行對應(yīng)的邏輯,之后返回給客戶端,當(dāng)然了,這一發(fā)一回復(fù)都是用的 RESP 協(xié)議特點(diǎn)的格式。
          一般情況下我們會使用 redis-cli或者一些客戶端工具連接 Redis 服務(wù)端。
          ./redis-cli
          然后整個交互過程的命令發(fā)送和返回結(jié)果像下面這樣,綠色部分為發(fā)送的命令,紅色部分為返回的結(jié)果。
          這就是我們再熟悉不過的部分了。但是,這并不能看出 RESP 協(xié)議的真實(shí)面貌。

          用 telnet 試試

          RESP 是基于 TCP 協(xié)議實(shí)現(xiàn)的,所以除了用各種客戶端工具以及 Redis 提供的 redis-cli工具,還可以用 telnet 查看,用 telnet 就可以看出 RESP 返回的原始數(shù)據(jù)格式了。
          我本地的 Redis 是用的默認(rèn) 6379 端口,并且沒有設(shè)置 requirepass ,我們來試一下用 telnet 連接。
          telnet?127.0.0.1?6379
          然后執(zhí)行與前面相同的幾條命令,發(fā)送和返回的結(jié)果如下,綠色部分為發(fā)送的命令,紅色為返回的結(jié)果。
          怎么樣,有些命令的返回還好,但是像get str:hello這條,返回的結(jié)果除了 world值本身,上面還多了一行 $5,是不是有點(diǎn)迷糊了。

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

          請求命令

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

          *<參數(shù)數(shù)量>?CR?LF
          $<參數(shù)?1?的字節(jié)數(shù)量>?CR?LF
          <參數(shù)?1?的數(shù)據(jù)>?CR?LF
          ...
          $<參數(shù)?N?的字節(jié)數(shù)量>?CR?LF
          <參數(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ī)則上就會變成下面這個樣子:
          *3\r\n$3\r\nset\r\n$9str:hello\r\n$5world\r\n

          服務(wù)端回復(fù)

          Redis 命令會返回多種不同類型的回復(fù)。
          通過檢查服務(wù)器發(fā)回數(shù)據(jù)的第一個字節(jié), 可以確定這個回復(fù)是什么類型:
          1、狀態(tài)回復(fù)(status reply)的第一個字節(jié)是 "+"
          比如 ping命令的回復(fù),+PONG\r\n
          2、錯誤回復(fù)(error reply)的第一個字節(jié)是 "-"
          比如輸入一個 redis 中不存在的命令,或者給某些命令設(shè)置錯誤的參數(shù),例如輸入 auth,auth 命令后面需要有一個密碼參數(shù)的,如果不輸入就會返回錯誤回復(fù)類型。
          -ERR wrong number of arguments for 'auth' command\r\n
          3、整數(shù)回復(fù)(integer reply)的第一個字節(jié)是 ":"
          例如 INCRDECR 自增自減命令,返回的結(jié)果是這樣的 :2\r\n
          4、批量回復(fù)(bulk reply)的第一個字節(jié)是 "$"
          例如對 string 類型執(zhí)行 get 操作,$5\r\nworld\r\n$后面的數(shù)字 5 表示返回的結(jié)果有 5 個字符,后面是返回結(jié)果的實(shí)際內(nèi)容。
          5、多條批量回復(fù)(multi bulk reply)的第一個字節(jié)是 "*"
          例如 LRANGE key start stop或者 hgetall等返回多條結(jié)果的命令,比如 lrange命令返回的結(jié)果:
          *2\r\n$6\r\nnews-2\r\n$6\r\nnews-1\r\n
          多條批量回復(fù)和前面說的客戶端發(fā)送命令的格式是一致的。

          ?

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

          了解了 Redis 的協(xié)議規(guī)則,我們就可以自己寫一個簡單的客戶端了。當(dāng)然,通過官網(wǎng)我們可以看到已經(jīng)有各種語言,而且每種語言有不止一個客戶端工具了。
          比如 Java 語言的客戶端就有這么多種,其中 Jedis 應(yīng)該是用的最多了,既然已經(jīng)有這么好用的輪子了,當(dāng)然沒必要重復(fù)造輪子,主要還是為了加深印象。
          RESP 協(xié)議基于 TCP 協(xié)議,可以使用 socket 方式進(jìn)行連接。

          public?Socket?createSocket()?throws?IOException?{
          ??Socket?socket?=?null;
          ??try?{
          ????socket?=?new?Socket();
          ????socket.setReuseAddress(true);
          ????socket.setKeepAlive(true);
          ????socket.setTcpNoDelay(true);
          ????socket.setSoLinger(true,?0);

          ????socket.connect(new?InetSocketAddress(host,?port),?DEFAULT_TIMEOUT);
          ????socket.setSoTimeout(DEFAULT_TIMEOUT);
          ????outputStream?=?socket.getOutputStream();
          ????inputStream?=?socket.getInputStream();
          ????return?socket;
          ??}?catch?(Exception?ex)?{
          ????if?(socket?!=?null)?{
          ??????socket.close();
          ????}
          ????throw?ex;
          ??}
          }

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

          有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)

          歡迎大家關(guān)注Java之道公眾號


          好文章,我在看??

          瀏覽 49
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美三级网站在线观看 | 9久精品| 奇米影视第四色7777 | 麻豆的视频高清在线观看完整 | 一级无码爱爱片免费 |