導讀:本文為Redis 作者 Antirez 就重點功能的發展方向做出澄清,並表明“Redis 沒有一個可靠的路線圖,多年來我發現走一步看一步才是優秀的路線圖”,閱讀此文,關註 Redis 功能研發方向。
昨天有位Redis 的使用者在Hacker News 上做了以下評論:
雖然我喜歡Redis,但我對目前正在開發的一些功能持懷疑態度。 respv3 協議中的一些功能,雖然聽起來很簡潔,但是也可能使客戶端程式碼複雜化。 還有細粒度ACL 需要的工作量很大。 我無法理解為什麼這些功能是必要的,或者說比其他功能(如多執行緒支援,更好的持久化模型,資料型別等)的優先順序更高。
很多使用者將ACL視為Redis Labs 強行新增的功能。 評論中的其他要點也很有趣,我相信這些都值得澄清,以便Redis 社群理解前方的道路。
為簡單起見,我將此部落格文章分為幾部分,對應原始評論中提到的每個功能。
RESP3
正如我在檔案上所寫的那樣,RESP3 的標的是簡化客戶端環境。我希望每個客戶端都有一個較低層次的抽象,不需要嘗試重新發明更高階別的介面,例如:redis.call(“get”,“foo”)。不再需要進行轉換,因為現有協議在語意上足以告訴客戶端response的結構,不需要事先知道大多數命令的元資料。我認為該使用者指的是 RESP3 對帶外通訊的支援,即回覆“屬性”。
我認為Redis 未來的“客戶端快取”將是非常重要的功能。這是每個可擴充套件系統的必經之路。但是如果沒有伺服器參與,客戶端快取失效將是一場噩夢。這就是為什麼 RESP3 需要支援回覆屬性。然而Redis 6 不會實現該功能。 Redis 現有不穩定版本將成為Redis 6.該版本已經有一個幾乎完整的RESP3(沒有實現屬性)實現。實現了RESP3 的客戶端可以先不支援屬 性,即使對於將來的Redis版本,也可能根本不傳送屬性資料。對於客戶端快取,必須將連線置於特殊樣式。此外,Redis 6 將完全向後相容RESP2。我認為RESP2 的支援永遠不會被移除,因為它是免費的,一旦我們嘗試在 RESP2 和 RESP3 之間實現一個抽象層,就沒有充分的理由來破壞向後相容性。
通常我不喜歡在沒有充分理由的情況下改變事物,但RESP2 的限制對客戶端生態系統有很大影響。我希望從一個客戶端到遷移另一個客戶端,使用者有賓至如歸的感受。API 都是Redis API,而不是客戶端作者單獨的特殊抽象。除了較低階別的API,我不反對更高階的API,但它們應該有一些共同點,客戶端應該能夠在不知道任何相關命令元資料的情況下傳送命令。
ACLs
四年前我自己修改了ACL 規範。我用了很長時間才說服自己現在是實現該功能的時候了:我們在沒有任何ACL 的情況需要使用命令重新命名等方式來達到目的。不能認為實現ACL 的主要動機是因為企業客戶需要安全性。ACL允許出於安全目的對使用者進行身份驗證,但該功能的主要標的是可運維。
舉例來說,你有一個Redis實體,並且計劃使用該實體來執行新操作:延遲作業處理。你從網際網路上下載了一個庫,它看起來沒啥問題。但是這個庫可以呼叫“FLUSHALL”並清除所有資料。也許只是庫的測試程式碼裡面有這樣的命令,然而你意識有問題的時候為時已晚。或者你剛好僱傭了一位喜歡在Redis 實體上呼叫“KEYS ”命令的”高階”開發人員。
另一種情況是雲供應商:他們需要小心地重新命名管理命令,甚至為了某些原因而遮蔽這些命令。使用ACL,你就能設定Redis,以便在沒有某些身份驗證的情況下,阻止預設使用者執行任何危險的操作。我認為這對運維來說將是一個很大的進步
此外,AC L是我為Redis AFAIK 寫的最好的程式碼之一。幾乎沒有CPU成本,除非您使用金鑰樣式,然而即便使用金鑰樣式,CPU 消耗依然很低。該實現都在acl.c檔案中,其餘的程式碼有一些對ACL API 的呼叫。ACL完全是模組化的,所以沒有增加系統複雜性。實際上,ACL 程式碼圍繞AUTH 命令也做了一些重構。
多執行緒
Redis 可能透過兩種方式獲得多執行緒支援。我相信使用者希望的是“memcached相似”的多執行緒,即能夠將單個Redis 實體擴充套件到多個執行緒,以便增加QPS。這種設計將I/O,命令解析等多執行緒化。所以我們稱之為“I/O執行緒”。
另一種多執行緒方法是允許在其他執行緒中執行慢速命令,以便不阻塞客戶端。我們將這種執行緒模型稱為“慢速命令執行緒”。
這就是計劃:I/O執行緒方案不會出現在Redis AFAIK中,因為經過深思熟慮之後,我認為該方案太複雜。大部分Redis 的瓶頸實際上是網路或記憶體。另外,我喜歡share-nothing,所以我想擴充套件Redis 的方法是改進其對同一主機中執行多個Redis實體的支援,特別是透過Redis Cluster。 因此,2019年主要集中在兩件事:
A)redis cluster多個實體能夠協調使用本地實體的磁碟,即避免AOF同時重寫。
B)我們將把Redis叢集代理作為Redis 專案的一部分釋出,這樣使用者就可以在沒有良好實現叢集協議客戶端的情況下抽象出叢集。
另外需要註意的是Redis不是Memcached,然而像memcached一樣,它是一個記憶體系統。對於非常簡單的資料模型來說多執行緒(如memcached)非常有意義。對於Redis來說,多執行緒磁碟儲存也是必須的。一個多執行緒的複雜記憶體系統將是非常複雜的:Redis 客戶端不是孤立的,資料結構也很複雜。例如,執行LPUSH 的執行緒需要服務於執行 LPOP 的其他執行緒。獲得的收益較少,新增的複雜性也很高。
相比之下,我想要解決的是慢操作問題,並且因為有了Redis 模組系統,我們已經走上了正確的方向。在將來(不確定是否在Redis 6或7中)我們會在模組系統中實現key 級鎖定,以便執行緒可以完全獲得對key 的控制以處理慢操作。現在,模組可以實現命令,並以完全獨立的方式為客戶端建立回覆,但仍然需要訪問共享資料集,這時候需要全域性鎖。
更好的儲存
最近我們做了多項努力,以改善Redis的基本功能。 最近的最優秀的實現是AOF檔案中的RDB前導碼。 Redis 4和5中還有很多關於複製的工作,與之相比現在的改進完全處另一個級別。 改進這些功能仍然是我的主要工作之一。
資料結構
從Redis 5 開始,Redis 就支援了Stream 結構。對於Redis 6和7,我們計劃最佳化一些實現,提高記憶體使用效率。 然而要新增新的資料結構,就需要做很多考慮。 我花了幾年時間才領悟到,如何在時間序列和 stream 的背景下使用stream 來彌合lists, pub/sub以及 sorted sets 的差異。 我希望Redis是一組使用者可以隨意組合的正交資料結構,而不是一組預定義的工具(使用者只能按照設計的方式使用)。 Streams是一個抽象日誌,所以我認為這是一個非常有價值的結構。 然而對於其他結構我不能完全確定它們是否值得加進核心功能。 無論如何,在最近幾年中,新增新資料結構的壓力肯定更大。 HyperLogLogs,更高階的位操作,stream,阻塞的sorted sets操作(ZPOP 和BZPOP )都是很好的例子。
結論
我相信Redis社群應該知道為什麼要做某事以及為什麼要推遲某些事情。我透過推特進行了大量溝通,但很多人並沒有關註這些內容。部落格是一種更好的告知社群的方式,因此我需要花時間寫部落格。需要註意的是,Redis沒有一個可靠的路線圖,多年來我發現走一步看一步才是優秀的路線圖。為Redis制定路線圖是愚蠢的,因為OSS核心團隊的規模很小,有時我會在幾個星期內陷入隨機崩潰……任何固定的長期計劃都行不通。此外,由於Redis社群提供反饋,我的想法發生了很大變化,所以我每個月都會重寫路線圖。部落格是一個很好的解決方案,至少可以顯示當前版本的優先事項/想法,並說明為什麼其他想法被放棄。
最後一點:我和Redis實驗室在開源專案方面的自由度幾乎是無限的。我認為這在行業中是一個奇跡,或者只是說在Redis Labs中的同事都是很好的人,他們明白我們所做的事情源於開源運動並且明智地保持這種方式。如果Redis路線圖出問題了,那肯定是我的錯誤。
原文地址:http://antirez.com/news/126
本文作者 Antirez,由方圓翻譯。轉載本文請註明出處,歡迎更多小夥伴加入翻譯及投稿文章的行列,詳情請戳公眾號選單「聯絡我們」。GIAC全球網際網路架構大會深圳站將於2019年6月舉行,屆時將有Redis相關話題,敬請期待。