自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

巧用 Redis pipeline 命令,解決真實的生產(chǎn)問題

存儲 存儲軟件 Redis
最近阿粉接到了一個業(yè)務(wù)需求,需要開發(fā)一個業(yè)務(wù)接口,批量刪除 Redis 中數(shù)據(jù)。這個功能點其實很簡單,只要讓外部傳入需要刪除鍵信息,然后在接口內(nèi)部遍歷調(diào)用刪除命令即可。

[[386481]]

本文轉(zhuǎn)載自微信公眾號「Java極客技術(shù)」,作者鴨血粉絲。轉(zhuǎn)載本文請聯(lián)系Java極客技術(shù)公眾號。

Hello,大家好,我是阿粉~

最近阿粉接到了一個業(yè)務(wù)需求,需要開發(fā)一個業(yè)務(wù)接口,批量刪除 Redis 中數(shù)據(jù)。

這個功能點其實很簡單,只要讓外部傳入需要刪除鍵信息,然后在接口內(nèi)部遍歷調(diào)用刪除命令即可。

按照這個思路,功能很快就開發(fā)完成,然后順利的上線。

上線之后,運行一段時間,調(diào)用業(yè)務(wù)方反饋,當要刪除的數(shù)據(jù)很多的時候,這個接口響應(yīng)時間就比較長,然后希望我們這邊優(yōu)化一下,降低響應(yīng)時間。

那優(yōu)化辦法其實有很多,比如使用多線程刪除等,不過這一次并沒有采用這個,最終使用了 Redis pipeline(管道)命令進行了優(yōu)化。

所以今天這篇文章就給大家介紹一下 Redis pipeline 命令,以及相關(guān)原理,文章涉及到知識點如下圖所示:

 

為什么多次調(diào)用 Redis 命令比較慢Redis 客戶端執(zhí)行一個命令需要經(jīng)歷流程如下圖所示:

 

總共需要經(jīng)過四個流程:

  1. 客戶端發(fā)送命令
  2. Redis 服務(wù)收到命令等待處理
  3. Redis 服務(wù)端處理命令
  4. Redis 服務(wù)返回執(zhí)行結(jié)果

Redis 的客戶端與服務(wù)可能部署在不同的機器上,這里我們假設(shè) Redis 客戶端部署在北京,而 Redis 服務(wù)端在廣州,兩地的網(wǎng)絡(luò)延時為 50ms。

一次 Redis 命令,1 與 4 這兩個流程就需要耗費 100ms, 而 2 與 3 在由于是在 Redis 服務(wù)端執(zhí)行,執(zhí)行速度會很快,可以忽略不計。

此時客戶端如果需要執(zhí)行 N 次 Redis 命令,我們就需要耗費 2N*100ms 時間,執(zhí)行命令越多,耗時越長。

這就是文章開頭 Redis 刪除多個命令比較慢的主要原因。

Redis pipeline 流水線執(zhí)行命令那如何解決這類問題了?

解決辦法有三種,第一種利用多線程機制,并行執(zhí)行命令,提高執(zhí)行速度。

第二種,調(diào)用 mget 這類命令,這類命令可以一次操作多個鍵,Redis 服務(wù)端收到命令之后,將會批量執(zhí)行。

但是 mget這類批量命令畢竟是少數(shù),很多情況下我們沒辦法直接使用,就像我們上面的例子。

這樣的話,只能使用最后一種辦法,使用 Redis pipeline命令。

開啟 Redis pipeline 之后,再執(zhí)行 Redis 的其他命令,命令將不會發(fā)送給服務(wù)端,而是先暫存在客戶端,左后等到所有命令都執(zhí)行完,然后再統(tǒng)一發(fā)送給服務(wù)端。

服務(wù)端會根據(jù)發(fā)送過來的命令的順序,依次運行計算。

然后同樣先將結(jié)果暫存服務(wù)端,等到命令都執(zhí)行完畢之后,統(tǒng)一返回給客戶端。

通過這種方式,減少多個命令之間網(wǎng)絡(luò)交互,有效的提高多個命令執(zhí)行的速度。

 

如上圖所示,開啟 Redis Pipeline 之后,客戶端運行的 5 個命令將會一起發(fā)送到服務(wù)端。服務(wù)依次運行命令,然后統(tǒng)一返回。

介紹完原理,我們來看下如何使用 Redis Pipeline ,下面代碼以 Jedis 為例。

  1. JedisPoolConfig poolConfig = new JedisPoolConfig(); 
  2. poolConfig.setMaxIdle(100); 
  3. poolConfig.setTestOnBorrow(false); 
  4. poolConfig.setTestOnReturn(false); 
  5.  
  6.  
  7. JedisPool jedisPool = new JedisPool(poolConfig, "127.0.0.1"Integer.parseInt("6379"), 60*1000, "1234qwer"); 
  8.  
  9. Jedis jedis = jedisPool.getResource(); 
  10.  
  11. Pipeline pipelined = jedis.pipelined(); 
  12.  
  13. for (int i = 0; i < 100; i++) { 
  14.     pipelined.set("key" + i, "value" + i); 
  15. pipelined.sync(); 

Jedis#pipelined 將會開啟 Redis Pipeline,而Pipeline 這個類提供所有 Redis 可以使用的命令:

 

當執(zhí)行完所有的命令之后,調(diào)用 Pipelined#sync 命令,所有命令數(shù)據(jù)將會統(tǒng)一發(fā)送到到 Redis 中。

上面的例子中,Pipelined#sync 方法調(diào)用之后不會返回任何結(jié)果。

如果此時需要處理 Redis 的返回值,那么我們需要調(diào)用 Pipelined#syncAndReturnAll 方法,這個方法返回值將會是一個集合,返回結(jié)果按照 Redis 命令的順序排序。

解密 pipeline 實現(xiàn)原理

Redis pipeline 命令的實現(xiàn),其實需要客戶端與服務(wù)端同時支持,并且實際執(zhí)行過程中,Redis pipeline 會根據(jù)需要發(fā)送命令數(shù)據(jù)量大小進行拆分,拆分成多個數(shù)據(jù)包進行發(fā)送。

這么做主要原因是因為,如果一次組裝 pipeline 數(shù)據(jù)量過大,一方面會增加客戶端的等待時間,而另一方面會造成一定的網(wǎng)絡(luò)阻塞。

不同 Redis 客戶端 pipeline 發(fā)送的最大字節(jié)數(shù)不太相同,比如 jedis-pipeline 每次最大發(fā)送字節(jié)數(shù)為8192。

下面我們從源碼側(cè),看下 jedis pipeline 實現(xiàn)機制。

Pipeline 所有命令方法,底層最終將會調(diào)用 Protocol#sendCommand方法,這個方法主要就是向 RedisOutputStream 輸出流中寫入數(shù)據(jù)。

 

RedisOutputStream#write方法如下圖所示:

 

這個方法內(nèi),一旦緩沖的數(shù)據(jù)大小超過指定大小,目前為 8192,就會立刻將數(shù)據(jù)全部寫入到真正輸出流中。

 

pipeline 多個命令實際發(fā)送流程圖如下所示:

 

一旦 Redis 客戶端將部分 pipeline 中執(zhí)行命令的發(fā)送給 Redis 服務(wù)端,服務(wù)端就會立即運行這些命令,然后返回給客戶端。

但是此時客戶端并不會去讀取,所以返回的響應(yīng)數(shù)據(jù)將會暫存在客戶端的 Socket 接收緩沖區(qū)中。

如果響應(yīng)數(shù)據(jù)比較大,填滿緩沖區(qū),此時客戶端會通過 TCP 流量控制機制,ACK 返回 WIN=0(接收窗口)來控制服務(wù)端不要再發(fā)送數(shù)據(jù)。

這時這些響應(yīng)數(shù)據(jù)將會一直暫存在 Redis 服務(wù)端輸出緩存中,如果數(shù)據(jù)比較多,將會占用很多內(nèi)存。

所以使用 Redis Pipeline 機制一定注意返回的數(shù)據(jù)量,如果數(shù)據(jù)很多,建議將包含大量命令的 pipeline 拆分成多次較小的 pipeline 來完成。

總結(jié)Redis 的 pipeline 命令可以批量執(zhí)行多個 redis 命令,它通過減少網(wǎng)絡(luò)的調(diào)用次數(shù),從而有效提高的多個命令執(zhí)行的速度。

 

不過我們使用過程,一定主要執(zhí)行數(shù)據(jù)的大小,如果數(shù)據(jù)過大,可以考慮將一個 pipeline 拆

 

責任編輯:武曉燕 來源: Java極客技術(shù)
相關(guān)推薦

2012-03-23 09:55:34

NETSH

2011-07-11 09:54:16

DAC登錄觸發(fā)器

2018-12-26 09:25:30

SQL ServerSQL語句數(shù)據(jù)庫

2018-05-21 20:58:44

人工智能云服務(wù)企業(yè)

2011-07-26 15:11:51

安全模式

2023-07-26 15:46:52

Docker管理容器

2021-01-05 08:12:42

SQL日期Spt

2023-10-11 22:24:00

DubboRedis服務(wù)器

2024-06-24 09:29:15

2012-09-26 10:20:06

數(shù)據(jù)庫

2017-01-05 14:19:06

Grep命令查找

2021-01-31 10:51:37

緩存lock數(shù)據(jù)

2024-07-12 08:48:50

2016-11-29 09:00:19

分布式數(shù)據(jù)一致性CAS

2019-10-23 09:00:06

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

2018-11-20 10:10:54

Redis數(shù)據(jù)庫模糊查詢

2010-11-24 15:22:51

MySQL命令行

2010-01-04 15:36:32

2020-09-14 07:35:40

Redis命令框架

2021-07-16 05:00:13

Environment開發(fā)生產(chǎn)
點贊
收藏

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