????????前面的幾章介紹了各式各樣的Redis命令以及使用這些命令來操作數(shù)據結構的方法,還列舉了幾個使用Redis來解決實際問題的例子。 為了讓讀者做好使用Redis構建真實軟件的準備, 本章將展示維護數(shù)據安全以及應對系統(tǒng)故障的方法。另外,本章還會介紹一些能夠在保證數(shù)據完整性的前提下提升Redis性能的方法。
????????本章首先會介紹Redis的各個持久化選項, 這些選項可以讓用戶將自己的數(shù)據存儲到硬盤上面。接著本章將介紹如何通過Redis的復制特性,把不斷更新的數(shù)據副本存儲到附加的機器上面, 從而提升系統(tǒng)的性能和數(shù)據的可靠性。 之后本章將會說明同時使用復制和持久化的好處和壞處, 并通過一些例子來告訴讀者應該如何去選擇適合自己的持久化選項和復制選項。 最后本章將對Redis的事務特性和流水線特性進行介紹, 并討論如何診斷某些性能問題。
????????閱讀這一章的重點是要弄懂更多的Redis運作原理,從而學會如何在首先保證數(shù)據正確的前提下,加快數(shù)據操作的執(zhí)行速度。
????????現(xiàn)在, 讓我們來看看Redis是如何將數(shù)據存儲到硬盤里面, 使得數(shù)據在Re山s重啟之后仍然存在的。
4.1 持久化選項
????????Redis提供了兩種不同的持久化方法來將數(shù)據存儲到硬盤里面。 一種方法叫快照(snapshotting)它可以將存在于某一時刻的所有數(shù)據都寫入硬盤里面。另一種方法叫只追加文件(append-onlyfile, AOF), 它會在執(zhí)行寫命令時,將被執(zhí)行的寫命令復制到硬盤里面。這兩種持久化方法既可以同時使用,又可以單獨使用,在某些情況下甚至可以兩種方法都不使用,具體選擇哪種持久化方法需要根據用戶的數(shù)據以及應用來決定。
????????將內存中的數(shù)據存儲到硬盤的一個主要原因是為了在之后重用數(shù)據,或者是為了防止系統(tǒng)故障而將數(shù)據備份到一個遠程位置。另外 , 存儲在Redis里面的數(shù)據有可能是經過長時間計算得出的,或者有程序正在使用Redis存儲的數(shù)據進行計算 , 所以用戶會希望自己可以將這些數(shù)據存儲起來以便之后使用,這樣就不必再重新計算了。對于一些Redis應用來說 , ”計算 ” 可能 只是簡單地將另一個數(shù)據庫的數(shù)據復制到Redis里面(2.4節(jié)中就介紹過這樣的例子),但對 于另外一些Redis應用來說,Redis存儲的數(shù)據可能是根據數(shù)十億行日志進行聚合分析得出的結果。
????????兩組不同的配置選項控制著Redis將數(shù)據寫入硬盤里面的方式,代碼清單4-1展示了這些配置選項以及它們的示例配置值。因為之后的 4.1. l 節(jié)和 4.1.2 節(jié)會更詳細地介紹這些選項,所以目前我們只要稍微了解一下這些選項就可以了。

????????代碼清單 4-1最開頭的幾個選項和快照持久化有關,比如:如何命名硬盤上的快照文件、多久執(zhí)行一次自動快照操作、是否對快照文件進行壓縮,以及在創(chuàng)建快照失敗后是否仍然繼續(xù)執(zhí)行寫命令。代碼清單的第二組選項用于配置AOF子系統(tǒng)(subsystem): 這些選項告訴Redis 是否使用AOF持久化、多久才將寫入的內容同步到硬盤、在對AOF進行壓縮(compaction)的時候能否執(zhí)行同步操作,以及多久執(zhí)行一次AOF壓縮。接下來的一節(jié)將介紹如何使用快照來保持數(shù)據安全。
4.1.1 快照持久化
????????Redis可以通過創(chuàng)建快照來獲得存儲在內存里面的數(shù)據在某個時間點上的副本。在創(chuàng)建快照之后,用戶可以對快照進行備份,可以將快照復制到其他服務器從而創(chuàng)建具有相同數(shù)據的服務器副本, 還可以將快照留在原地以便重啟服務器時使用。
????????根據配置, 快照將被寫入dbfilename選項指定的文件里面, 并儲存在dir選項指定的路徑上面。 如果在新的快照文件創(chuàng)建完畢之前, Redis、 系統(tǒng)或者硬件這三者之中的任意一個崩潰了, 那么Reclis將丟失最近一次創(chuàng)建快照之后寫入的所有數(shù)據。
????????舉個例子,假設Redis目前在內存里面存儲了10GB的數(shù)據,上一個快照是在下午2:35開始創(chuàng)建的, 并且已經創(chuàng)建成功。 下午3:06時, Redis又開始創(chuàng)建新的快照, 并且在下午3:08快照文件創(chuàng)建完畢之前,有35個鍵進行了更新。 如果在下午3:06至下午3:08期間, 系統(tǒng)發(fā)生崩潰, 導致Redis無法完成新快照的創(chuàng)建工作,那么Redis將丟失下午2:35之后寫入的所有數(shù)據。另一方面, 如果系統(tǒng)恰好在新的快照文件創(chuàng)建完畢之后崩潰,那么Redis將只丟失35個鍵的更新數(shù)據。
創(chuàng)建快照的辦法有以下幾種:
? 客戶端可以通過向Redis發(fā)送BGSAVE命令來創(chuàng)建一個快照。 對千支持BGSAVE命令的平臺來說(基本上所有平臺都支持, 除了Windows平臺),Redis會調用fork1D來創(chuàng)建一 個子進程, 然后子進程負責將快照寫入硬盤, 而父進程則繼續(xù)處理命令請求。
? 客戶端還可以通過向Redis發(fā)送SAVE命令來創(chuàng)建一個快照, 接到SAVE命令的Redis服務器在快照創(chuàng)建完畢之前將不再響應任何其他命令。 SAVE命令并不常用,我們通常只會在沒有足夠內存去執(zhí)行BGSAVE命令的清況下, 又或者即使等待持久化操作執(zhí)行完畢也無所謂的情況下,才會使用這個命令。
? 如果用戶設置了save配置選項, 比如save 60 10000, 那么從Redis最近一次創(chuàng)建快照之后開始算起,當"60秒之內有10 000次寫入“ 這個條件被滿足時,Redis就會自動觸發(fā)BGSAVE命令。 如果用戶設置了多個save配置選項, 那么當任意一個save配置選項所設置的條件被滿足時,Re山s就會觸發(fā)一次BGSAVE命令。
? 當Redis通過SHUTDOWN命令接收到關閉服務器的請求時, 或者接收到標準TERM信號時, 會執(zhí)行一個SAVE命令, 阻塞所有客戶端,不再執(zhí)行客戶端發(fā)送的任何命令, 并在SAVE命令執(zhí)行完畢之后關閉服務器。
? 當一個Redis服務器連接另一個Redis服務器, 并向對方發(fā)送SYNC命令來開始一次復制操作的時候,如果主服務器目前沒有在執(zhí)行BGSAVE操作, 或者主服務器并非剛剛執(zhí)行完BGSAVE操作, 那么主服務器就會執(zhí)行BGSAVE命令。更多有關復制的信息請參考4.2節(jié)。
? ??????在只使用快照持久化來保存數(shù)據時, 一定要記?。喝绻到y(tǒng)真的發(fā)生崩潰, 用戶將丟失最近一次生成快照之后更改的所有數(shù)據。 因此,快照持久化只適用于那些即使丟失一部分數(shù)據也不會造成問題的應用程序, 而不能接受這種數(shù)據損失的應用程序則可以考慮使用4.1.2節(jié)中介紹的AOF持久化。
4.1.2 AOF持久化
????????簡單來說, AOF持久化會將被執(zhí)行的寫命令寫到AOF文件的末尾, 以此來記錄數(shù)據 發(fā)生的變化。 因此, Redis只要從頭到尾重新執(zhí)行一次AOF文件包含的所有寫命令, 就可以恢復AOF文件所記錄的數(shù) 據集。 AOF持久 化可以通 過設置代碼清單4-1 所示的appendonly yes配置選項來打開。 表4-1展示了appendfsync配置選項對AOF文件的同步頻率的影響。

????????如果用戶使用appendfsyncalways選項的話, 那么每個Redis 寫命令都會被寫入硬盤,從而將發(fā)生系統(tǒng)崩潰時出現(xiàn)的數(shù)據丟失減到最少。不過遺憾的是, 因為這種同步策略需要對硬盤進行大量寫入, 所以Redis處理命令的速度會受到硬盤性能的限制:轉盤式硬盤(spinning disk)在這種同步頻率下每秒只能處理大約200 個寫命令, 而固態(tài)硬盤(solid-state drive, SSD) 每秒大概也只能處理幾萬個寫命令。
? ??????為了兼顧數(shù)據安全和寫入性能, 用戶可以考慮使用appendfsync everysec選項,讓Redis以每秒一次的頻率對AOF 文件進行同步。Re山s每秒同步一次AOF 文件時的性能和不使用任何持久化特性時的性能相差無幾, 而通過每秒同步一次AOF 文件,Re山s可以保證, 即使出現(xiàn)系統(tǒng)崩潰, 用戶也最多只會丟失一秒之內產生的數(shù)據。當硬盤忙于執(zhí)行寫入操作的時候, Redis還會優(yōu)雅地放慢自己的速度以便適應硬盤的最大寫入速度。
????????最后, 如果用戶使用appendfsync no選項,那么Redis 將不對AOF 文件執(zhí)行任何顯式的同步操作, 而是由操作系統(tǒng)來決定應該在何時對AOF 文件進行同步。這個選項在一般情況下不會對Redis的性能帶來影響, 但系統(tǒng)崩潰將導致使用這種選項的Redis服務器丟失不定數(shù)量的數(shù)據。另外, 如果用戶的硬盤處理寫入操作的速度不夠快的話,那么當緩沖區(qū)被等待寫入硬盤的數(shù)據填滿時, Redis的寫入操作將被阻塞, 并導致Redis處理命令請求的速度變慢。因為這個因,一般來說并不推薦使用appendfsyncno選項, 在這里介紹它只是為了完整列舉appendfsync選項可用的3個值。
????????雖然AOF 持久化非常靈活地提供了多種不同的選項來滿足不同應用程序對數(shù)據安全的不同要求, 但AOF 持久化也有缺陷??隨就是AOF 文件的體積大小。
4.1.3 重寫/壓縮AOF文件
? ??????在閱讀了上一節(jié)對AOF 持久化的介紹之后, 讀者可能會感到疑惑: AOF 持久化既可以將丟失數(shù)據的時間窗口降低至1秒(甚至不丟失任何數(shù)據), 又可以在極短的時間內完成定期的待久化操作, 那么我們有什么理由不使用AOF持久化呢?但是這個問題實際上并沒有那么簡單, 因為Redis會不斷地將被執(zhí)行的寫命令記錄到AOF文件里面, 所以隨著Redis不斷運行,AOF文件的體積也會不斷增長, 在極端情況下, 體積不斷增大的AOF文件甚至可能會用完硬盤的所有 可用空間 。還有另一個問題就是, 因為Redis在重啟之后需要 通過重新執(zhí)行AOF文件記錄的所有寫命令來還原數(shù)據集, 所以如果AOF文件的體積非常大, 那么還原操作執(zhí)行的時間就可能會非常長。
? ??????為了解決AOF文件體積不斷增大的問題, 用戶可以向Redis發(fā)送BGREWRITEAOF命令, 這個命令會通過移除AOF文件中的冗余命令來重寫(rewrite)AOF文件, 使AOF文件的體積變得盡可能地小。 BGREWRITEAOF的工作原理和 BGSAVE創(chuàng)建快照的工作原理非常相似: Redis會創(chuàng) 建一個子進程, 然后由子進程負責對AOF文件進行重寫。 因為AOF文件重寫也需要 用到子進程, 所以快照待久化因為創(chuàng)建子進程而導致的性能問題和內存占用問題, 在AOF持久化中也同樣存 在。 更糟糕的是, 如果不加以控制的話,AOF 文件的體積可能會比快照文件的體積大好幾倍,在進行AOF重寫并刪除舊AOF文件的時候, 刪除一個體積達到數(shù)十GB大的舊AOF文件可能會導致操作系統(tǒng)掛起(hang)數(shù)秒。
????????跟快照持久化可以通過設置 save選項來自動執(zhí)行BGSAVE一樣,AOF持久化也可以通過設置 auto-aof-rewrite-percentage選項和auto-aof-rewrite-rnin-size選項來自動執(zhí)行BGREWRITEAOF。舉個例子, 假設用戶對Redis設置了配置選項auto-aof-rewrite-percentage 100和 auto-aof-rewrite-rnin-size 64rnb, 并且啟用了AOF持久化, 那么當AOF文件的體積大于64MB, 并且AOF文件的體積比上 次重寫之后的體積大了至少 倍(100%)的時候,Redis將執(zhí)行BGREWRITEAOF命令。 如果AOF重寫執(zhí)行得過于頻繁的話, 用戶可以考慮將 auto-aof-rewrite-percentage選項的值設置為100以上, 這種做法可以讓Redis在AOF 文件的體積變得更大之后才執(zhí)行重寫操作, 不過也會讓Redis在啟動時還原數(shù)據集所需的時間變得更長。
????????無論是使用AOF待久化還是快照持久化, 將數(shù)據持久化到硬盤上都是非常有必要的, 但除 了進行持久化之外, 用戶還必須對待久化所得的文件進行備份(最好是備份到多個不同的地方),這樣才能盡量避免數(shù)據丟失事故發(fā)生。 如果條件允許的話, 最好能將快照文件和最新重寫的AOF文件備份到不同的服務器上面。
????????通過使用AOF持久化或者快照持久化, 用戶可以在系統(tǒng)重啟或者崩潰的情況下仍然保留數(shù)據。 隨著負載量的上升, 或者數(shù)據的完整性變得越來越重要時, 用戶可能需要使用復制特性。
4.2 復制
????????對于有擴展平臺以適應更高負載經驗的工程師和管理員來說, 復制(replication)是不可或缺的 。復制可以讓其他服務器擁有 個不斷地更新的數(shù)據副本,從而使得擁有數(shù)據副本的服務器可以用于處理客戶端發(fā)送的讀請求。關系數(shù)據庫通常會使用一個主服務器(master)向多個從服務器(slave)發(fā)送更新, 并使用從服務器來處理所有讀請求。 Redis也采用了同樣的方法來實現(xiàn)自己的復制特性,并將其用作擴展性能的一種手段。 本節(jié)將對Redis的復制配置選項進行討論,并說明Redis在進行復制時的各個步驟。
????????盡管Redis的性能非常優(yōu)秀,但它也會遇上沒辦法快速地處理請求的情況, 特別是在對集合和有序集合進行操作的時候, 涉及的元素可能會有上萬個甚至上百萬個, 在這種情況下,執(zhí)行操 作所花費的時間可能需要以秒來進行計算, 而不是毫秒或者微秒。但即使一個命令只需要花費10毫秒就能完成,單個Redis實例(ins畫ce) 1秒也只能處理100個命令。
? ??????在需要擴展讀請求的時候,或者在需要寫入臨時數(shù)據的時候(第7章對此有詳細的介紹),用戶可以通過設置額外的Redis從服務器來保存數(shù)據集的副本。在接收到主服務器發(fā)送的數(shù)據初始副本(initialcopy of the data)之后,客戶端每次向主服務器進行寫入時,從服務器都會實時地得到更新。在部署好主從服務器之后, 客戶端就可以向任意一個從服務器發(fā)送讀請求了, 而不必再像之前一樣, 總是把每個讀請求都發(fā)送給主服務器(客戶端通常會隨機地選擇使用哪個從服 務器,從而將負載平均分配到各個從服務器上)。
4.2.1 對Redis 的復制相關選項進行配置
????????4.1.1節(jié)中曾經介紹過, 當從服務器連接主服務器的時候, 主服務器會執(zhí)行BGSAVE操作。因此為了正確地使用復制特性, 用戶需要保證主服務器已經正確地設置了代碼清單4-1里面列出的dir選項和dbfilename選項, 并且這兩個選項所指示的路徑和文件對于Redis進程來說都是可寫的(writable)。
????????盡管有多個不同的選項可以控制從服務器自身的行為,但開啟從服務器所必須的選項只有slaveof一個。如果用戶在啟動Redis服務器的時候,指定了一個包含slaveof host port選項的配置文件,那么Redis服務器將根據該選項給定的IP地址和端口號來連接主服務器。對于一個正在運行的Redis服務器, 用戶可以通過發(fā)送SLAVEOF no one命令來讓服務器終止復制操作,不再接受主服務器的數(shù)據更新;也可以通過發(fā)送SLAVEOF host port命令來讓服務器開始復制一個新的主服務器。
????????開啟Redis的主從復制特性并不需要進行太多的配置, 但了解Redis服務器是如何變成主服務器或者從服務器的, 對于我們來說將是非常有用的和有趣的過程。
4.2.2?Redis 復制的啟動過程
????????本章前面曾經說過, 從服務器在連接一個主服務器的時候,主服務器會創(chuàng)建一個快照文件并將其發(fā)送至從服務器,但這只是主從復制執(zhí)行過程的其中一步。 表4-2完整地列出了當從服務器連接主服務器時, 主從服務器執(zhí)行的所有操作。

????????通過使用表4-2所示的辦法,Redis在復制進行期間也會盡可能地處理接收到的命令請求,但是, 如果主從服務器之間的網絡帶寬不足, 或者主服務器沒有足夠的內存來創(chuàng)建子進程和創(chuàng)建記錄寫命令的緩沖區(qū), 那么Redis處理命令請求的效率就會受到影響。因此, 盡管這并不是必須的,但在實際中最好還是讓主服務器只使用50%??65%的內存, 留下30%??45%的內存用于執(zhí)行BGSAVE命令和創(chuàng)建記錄寫命令的緩沖區(qū)。
????????設置從服務器的步驟非常簡單, 用戶既可以通過配置選項SLAVEOF host port來將一個Redis服務器設置為從服務器, 又可以通過向運行中的Redis服務器發(fā)送SLAVEOF命令來將其設置為從服務器。如果用戶使用的是SLAVEOF配置選項, 那么Redis在啟動時首先會載入當前可用的任何快照文件或者AOF文件, 然后連接主服務器并執(zhí)行表4-2所示的復制過程。如果用戶使用的是SLAVEOF命令, 那么Redis會立即嘗試連接主服務器, 并在連接成功之后, 開始表4-2所示的復制過程。
? ??????當多個從服務器嘗試連接同一個主服務器的時候, 就會出現(xiàn)表 4-3 所示的兩種情況中的其中 一種。

????????在大部分情況下, Redis 都會盡可能地減少復制所需的工作, 然而,如果從服務器連接主服務器的時間并不湊巧, 那么主服務器就需要多做一些額外的工作。另一方面, 當多個從服務器同時連接主服務器的時候,同步多個從服務器所占用的帶寬可能會使得其他命令請求難以傳遞給主服務器, 與主服務器位于同一網絡中的其他硬件的網速可能也會因此而降低。
4.2.3 主從鏈
? ??????有些用戶發(fā)現(xiàn) , 創(chuàng)建多個從服務器可能會造成網絡不可用一當復制需要通過互聯(lián)網進行或 者需要在不同數(shù)據中心之間進行時, 尤為如此。 因為 Redis 的主服務器和從服務器并沒有特別不 同的地方, 所以從服務器也可以擁有自己的從服務器,并由此形成主從鏈 (master/slave chaining)。
????????從服務器對從服務器進行復制在操作上和從服務器對主服務器進行復制的唯一區(qū)別在于 , 如果從服務器X擁有從服務器 Y, 那么當從服務器X在執(zhí)行表 4-2 中的步驟 4 時 , 它將斷開與從 服務器 Y的連接 , 導致從服務器 Y需要重新連接并重新同步 (resync)。
????????當讀請求的重要性明顯高于寫請求的重要性,并且讀請求的數(shù)拭遠遠超出一臺 Redis 服務器 可以處理的范圍時,用戶就需要添加新的從服務裸來處理讀請求。 隨著負載不斷上升,主服務器 可能會無法快速地更新所有從服務器,或者因為重新連接和重新同步從服務器而導致系統(tǒng)超載。 為了緩解這個問題, 用戶可以創(chuàng)建一個由 Redis 主從節(jié)點 (master/slave node) 組成的中間層來分擔主服務器的復制工作,如圖4-1所示。

????????盡管主從服務器之間并不一定要像圖4-1那樣組成一個樹狀結構,但記住并理解這種樹狀結構對于Redis復制來說是可行的(possible)并且是合理的(reasonable)將有助于讀者理解之后的內容。本書在前面的4.1.2節(jié)中曾經介紹過, AOF持久化的同步選項可以控制數(shù)據丟失的時間長度:通過將每個寫命令同步到硬盤里面, 用戶幾乎可以不損失任何數(shù)據(除非系統(tǒng)崩潰或者硬盤驅動器損壞), 但這種做法會對服務器的性能造成影響;另一方面, 如果用戶將同步的頻率設置為每秒一次, 那么服務器的性能將回到正常水平, 但故障可能會造成1秒的數(shù)據丟失。通過同時使用復制和AOF持久化, 我們可以將數(shù)據持久化到多臺機器上面。
????????為了將數(shù)據保存到多臺機器上面, 用戶首先需要為主服務器設置多個從服務器, 然后對每個從服務器設置appendonly yes選項和appendfsync everysec選項(如果有需要的話,也可以對主服務器進行相同的設置), 這樣的話, 用戶就可以讓多臺服務器以每秒一次的頻率將數(shù)據同步到硬盤上了。但這還只是第一步: 因為用戶還必須等待主服務器發(fā)送的寫命令到達從服務器, 并且在執(zhí)行后續(xù)操作之前, 檢查數(shù)據是否已經被同步到了硬盤里面。
4.4 Redis事務
????????為了保證數(shù)據的正確性, 我們必須認識到這一點:在多個客戶端同時處理相同的數(shù)據時, 不謹慎的操作很容易會導致數(shù)據出錯。本節(jié)將介紹使用Redis事務來防止數(shù)據出錯的方法, 以及在 某些情況下, 使用事務來提升性能的方法。
? ??????Redis的事務和傳統(tǒng)關系數(shù)據庫的事務并不相同。在關系數(shù)據庫中, 用戶首先向數(shù)據庫服務器發(fā)送BEGIN, 然后執(zhí)行各個相互一致(consistent)的寫操作和 讀操作, 最后, 用戶可以選擇發(fā)送COMMIT 來確認之前所做的修改, 或者發(fā)送ROLLBACK來放棄那些修改。
????????在Redis里面也有簡單的方法可以處理一連串相互一致的讀操作和寫操作。正如本書在3.7.2節(jié)中介紹的那樣, Redis的事務以特殊命令MULTI為開始, 之后跟著用戶傳入的多個命令, 最后以EXEC為結束。但是由于這種簡單的事務在EXEC命令被調用之前不會執(zhí)行任何實際操作, 所以用戶將沒辦法根據 讀取到的數(shù)據來做決定。這個問題看上去似乎無足輕重, 但實際上無法以 一致的形式讀取數(shù)據將導致某一類型的問題變得難以解決, 除此之外, 因為 在多個事務同時處理同一個對象時通常需要用到二階提交(two-phase commit), 所以如果事務不能以 一致的形式讀取數(shù)據, 那么二階提交將無法實現(xiàn), 從而導致一些原本可以成功執(zhí)行的事務淪落至執(zhí)行失敗的地步。?
????????為什么Redis沒有實現(xiàn)典型的加鎖功能? 在訪問以寫入為目的數(shù)據的時候(SQL中的 SELECT FOR UPDATE), 關系數(shù)據庫會對被訪問的數(shù)據行進行加鎖, 直到事務被提交(COMMIT) 或者被回滾(ROLLBACK)為止 . 如果有其他客戶端試圖對被加鎖的數(shù)據行進行寫入, 那么該客戶端將被阻塞, 直到笫一個事務執(zhí)行完畢為止. 加鎖在實際使用中非常有效, 基本上所有關系數(shù)據庫都實現(xiàn)了這種加鎖功能, 它的缺點在于, 持有鎖的客戶端運行越慢, 等待解鎖的客戶端被阻塞的時間就越長.
????????因為加鎖有可能會造成長時間的等待, 所以Redis為了盡可能地減少客戶端的等待時問, 并不會在執(zhí)行WATCH命令時對數(shù)據進行加鎖. 相反地,Redis只會在數(shù)據已經被其他客戶端搶先修改了的情況下 , 通知執(zhí)行了 WATCH命令的客戶端, 這種做法被稱為樂觀鎖(optimitic locking), 而關系數(shù)據庫實際執(zhí)行的加鎖操作則被稱為悲觀鎖(pessimistic locking)。 樂觀鎖在實 際使用中同樣非常有效, 因為客戶端永遠不必花時間去等待第一個取得鎖的客戶端——它們只 需要在自己的事務執(zhí)行失敗時進行重試就可以了.
? ??????當有多個客戶端同時對相同的數(shù)據進行操作時,正確地使用事務可以有效地防止數(shù)據錯誤發(fā)生。 而接下來的一節(jié)將向我們展示,在無需擔心數(shù)據被其他客戶端修改了的情況下,如何以 更快的速度執(zhí)行操作。
4.5 非事務型流水線
????????第3章在首次介紹 MULTI和EXEC的時候討論過它們的 ”事務“ 性質——被MULTI和 EXEC包裹的命令在執(zhí)行時不會被其他客戶端打擾。 而使用事務的其中一個好處就是底層的客戶 端會通過使用流水線來提高事務執(zhí)行時的性能。本節(jié)將介紹如何在不使用事務的情況下, 通過 使用流水線來進一步提升命令的執(zhí)行性能。
? ??????第2章曾經介紹過一些可以接受多個參數(shù)的添加命令和更新命令, 如MGET、MSET、HMGET、 HMSET、 RPUSH和LPUSH、 SADD、 ZADD等。 這些命令簡化了那些需要重復執(zhí)行相同命令的操作,并且極大地提升了性能。盡管效果可能沒有以上提到的命令那么顯著 , 但使用非事務型流水線(non-transactional pipeline)同樣可以獲得相似的性能提升,并且可以讓用戶同時執(zhí)行多個不同的命令。
4.6 關于性能方面的注意事項
????????要對Redis的性能進行優(yōu)化, 用戶首先需要弄清楚各種類型的Redis命令到底能跑多快, 而 這一點可以通過調用Redis附帶的性能測試程序redis-benchmark來得知,.