說說 Redis pipeline

来源:https://www.cnblogs.com/immaxfang/archive/2022/10/23/16819288.html
-Advertisement-
Play Games

更多技術文章,請關註我的個人博客 www.immaxfang.com 和小公眾號 Max的學習札記。 Redis 客戶端和服務端之間是採用 TCP 協議進行通信的,是基於 Request/Response 這種一問一答的模式,即請求一次響應一次。 普通模式 我們先來看下普通模式下,一條 Redis ...


更多技術文章,請關註我的個人博客 www.immaxfang.com 和小公眾號 Max的學習札記

Redis 客戶端和服務端之間是採用 TCP 協議進行通信的,是基於 Request/Response 這種一問一答的模式,即請求一次響應一次。

普通模式

我們先來看下普通模式下,一條 Redis 命令的簡要執行過程:

  • 客戶端發送一條命令給 redis-server,阻塞等待 redis-server 應答
  • redis-server 接收到命令,執行命令
  • redis-server 將結果返回給客戶端

image.png
下麵我們來簡要瞭解下一個完整請求的交互過程。
image.png

  1. 客戶端調用 write() 將消息寫入操作系統為 socket 分配的 send buffer 中
  2. 操作系統將 send buffer 中的內容發送到網卡,網卡通過網關路由把內容發送到伺服器網卡
  3. 伺服器網卡將接受到的消息寫入操作系統為 socket 分配的 recv buffer
  4. 伺服器進程調用 read() 從 recv buffer 中讀取消息進行處理
  5. 處理完成之後,伺服器調用 write() 將響應內容發送的 send buffer 中
  6. 伺服器將 send buffer 中的內容通過網卡,發送到客戶端
  7. 客戶端操作系統將網卡中的內容放入 recv buffer 中
  8. 客戶端進程調用 read() 從 recv buffer 中讀取消息

普通模式的問題

我們來想一下,這種情況下可能導致什麼問題。
如果同時執行大量的命令,那對於每一個命令,都要按上面的流程走一次,當前的命令需要等待上一條命令執行應答完畢之後,才會執行。這個過程中會有多次的 RTT ,也還會伴隨著很多的 IO 開銷,發送網路請求等。每條命令的發送和接收的過程都會占用兩邊的網路傳輸。
簡單的來說,每個命令的執行時間 = 客戶端發送耗時 + 伺服器處理耗時 + 伺服器返回耗時 + 一個網路來回耗時。
在這裡,一個 網路來回耗時(RTT) 是不好控制的,也是不穩定的。它的影響因素很多,比如客戶端到伺服器的網路線路是否擁堵,經過了多少跳。還有就是 IO 系統調用也是耗時的,一個 read 系統調用,需要從用戶態,切換到內核態。上文我們講述一個命令的請求過程時多次降到 read 和 write 系統調用。
可以說一個命令的執行時間,很大程度上受到它們的限制。

pipeline 模式

有沒有什麼方法來解決這種問題呢。
第一種方法,就是利用多線程機制,並行執行命令。
第二種方法,調用批量命令,例如 mget等,一次操作多個鍵。
很多時候我們要執行的命令並不是一樣的命令,而是一組命令,這個時候就無法使用類似 mget這樣的批量命令了。那還有其他的方法嗎?
回想一下,我們初學編程的時候,老手都會告訴我們,不要在迴圈裡面做查詢。我有一個 books 列表數據,要根據 book_id 查詢它們的 price,如果我們迴圈 books 列表,在每次迴圈裡面取查詢單個 book_id 的 price,那性能肯定是不理想的。一般我們的優化方式是將多個 book_id 取出來,一次性去查多個 book_id 的 price,這樣性能就有明顯的提示。即將多次小命令中的耗時操作合併到一次,從而減少總的執行時間。
類似的,Redis pipeline 出現了,一般稱之為管道。它允許客戶端一次可以發送多條命令,而不用像普通模式那樣每次執行一個小命令都要等待前一個小命令執行完,伺服器在接收到一堆命令後,會依次執行,然後把結果打包,再一次性返回給客戶端。
這樣可以避免頻繁的命令發送,減少 RTT,減少 IO 調用次數。前面已經介紹了,IO 調用會涉及到用戶態和內核態之間的切換,在高性能的一些系統中,我們都是儘可能的減少 IO 調用。
簡要流程如下圖:
image.png

  • pipeline 的優點
    • 減少 RTT
    • 減少 IO 調用次數
  • 基本使用
Pipeline pipeline =jedis.pipelined();

for(int i = 0; i < 100; i++){
    pipeline.rpush("rediskey", i + "");
}

pipeline.sync()

總結一下 pipeline 的核心,就是客戶端將一組 Redis 命令進行組裝,通過一次 RTT 發送給伺服器,同時伺服器再將這組命令的執行結果按照順序一次返回給客戶端

pipeline 註意問題

雖然 pipeline 在某些情況下會帶來不小的性能提升,但是,我們在使用的時候也需要註意。

  • pipeline 中的命令數量不宜過多。

客戶端會先將多個命令寫入記憶體 buffer 中(打包),命令過多,如果是超過了客戶端設置的 buffer 上限,被客戶端的處理策略處理了(不同的客戶端實現可能會有差異,比如 jedis pipeline ,限制每次最大的發送位元組數為 8192,緩衝區滿了就發送,然後再寫緩衝,最後才處理 Redis 伺服器的應答)。如果客戶端沒有設置 buffer 上限或不支持上限設置,則會占用更多的客戶端機器記憶體,造成客戶端癱瘓。官方推薦是每次 10k 個命令。
建議做好規範,遇到一次包含大量命令的 pipeline,可以拆分成多個稍小的 pipeline 來完成。

  • pipeline 一次只能運行在一個 Redis 節點上,一些集群或者 twemproxy 等中間件使用需要註意。

在集群環境下,一次 pipeline 批量執行多個命令,每個命令需要根據 key 計算槽位,然後根據槽位去特定的節點上去執行命令,這樣一次 pipeline 就會使用多個節點的 redis 連接,這種當前也是不支持的。

  • pipeline 不保證原子性,如要求原子性,不建議使用 pipeline

它僅是將多個命令打包發送出去而已,如果中間有命令執行異常,也會繼續執行剩餘命令。

pipeline 與批量操作 mget 等區別

其實 meget和 pipeline 優化的方向是一致的,即多個命令打包一次發送,減少網路時間。但是也是有區別的。

  • mget等的場景是一個命令對應多個鍵值對,而 pipeline 一般是多條命令(不同的命令)
  • mget操作是一個原子操作,而 pipeline 不是原子操作
  • mget是服務端實現,而 pipeline 是客戶端和服務端共同實現

pipeline 與事務的區別

這兩者關註和解決的問題不是一個東西,原理也不一樣。

  • pipeline 是一次請求,服務端順序執行,一次返回。而事務是多次請求(先 multi,再多個操作命令,最後 exec),服務端順序執行,一次返回
  • pipeline 關註的是 RTT 時間和 IO 調用,事務關註的是一致性問題

總結

本文主要講了多命令執行時耗時問題,以及 pipeline 的解決方法,和其簡單的原理,以及註意點。今天的學習就到這裡,改天我們接著肝。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文將介紹三種資料庫變慢場景的分析與優化方法. 1、已經定位出的特定慢SQL 2、整個資料庫實例(幾乎所有SQL)變慢, 或者某些時候整個資料庫實例大面積SQL變慢(大面積抖動) 3、某些正常情況下很快的SQL偶爾會變慢(抖動) ...
  • HTML (HyperText Markup Language,超文本標記語言) 不是一門編程語言,而是一種用於定義內容結構的標記語言,用來描述網頁內容,文件格式為.html。HTML 由一系列的元素(elements)組成,這些元素用來實現不同的內容。HTML5是HTML新的修訂版本,2014年由... ...
  • 函子(Functor) 函子是一個特殊的容器,通過一個普通對象來實現,該對象具有map方法,map方法可以運行一個函數對值進行處理(變形關係),容器包含值和值變形關係(這個變形關係就是函數)。函數式編程中解決副作用的存在 函數式編程的運算不直接操作值,,而是由函子完成 函子就是一個實現了map契約的 ...
  • 需求 實現sum函數,使其可以傳入不定長參數,以及不定次數調用 //示例 console.log(sum(1,2)(3)()) //6 console.log(sum(2,3,4,5)(1,2)(3)(4)()) //23 需求分析 實現sum函數我們可以考慮可以使用閉包的形式來實現 因為每次傳參, ...
  • 先上結論: 防抖 :只執行最後一次 (常用語輸入框) 節流: 控制執行的次數 (常下拉滾動條時進行數據請求) 防抖代碼: (這是未封裝的,防抖代碼和業務代碼寫在一起了) <body> <input type="text" /> <script> // 防抖:用戶觸發事件過於頻繁,只要最後一次事件的操 ...
  • 2022-10-21 第一個vue.js <!doctype html> <head> <title>Document</title> <!-- 開發環境 --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> ...
  • 網路上很多關於JS原型的理解,寫了很多,我也看了很多,但總是雲里霧裡,很多文章一上來就說Object是一切對象的根對象,這句話非常誤導人的思維,後來自己在控制台,自己分析出來了比較好理解的方式,下麵我來詳細屢屢關於js原型的正確理解方式。 主要是理解js中的對象,函數,函數對象,函數實例 首先我們來 ...
  • 什麼是事件委托: 通俗的講,事件就是onclick,onmouseover,onmouseout,等就是事件,委托呢,就是讓別人來做,這個事件本來是加在某些元素上的。 原理: 利用冒泡的原理,把事件加到父級上,觸發執行效果。 例如:要點擊刪除 ul 下的 li ,一般是都要給每個小li 綁定點擊事件 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...