在這篇博文中,他們用 SQLite 取代了 Redis,而令人驚訝的是,SQLite 的速度更快!有趣的是,Redis 是在本地執行,而 SQLite 是將資料儲存在磁碟上。因此,這是記憶體(Redis)與磁碟(SQLite)的較量,但 Redis 需要透過 IPC 進行通訊。
人們一直以為磁碟 I/O 比 IPC 慢,但顯然這並不總是正確的!實際上,IPC 也可能更慢!Redis自己也承認這點
Wafris重新架構了它的系統,從Redis遷移到SQLite,以提高簡單性和效能。這篇部落格文章詳細介紹了為什麼SQLite更適合他們的需求,重點是它如何簡化快取和最佳化網站效能。如果你對網路安全和流量管理的架構決策感興趣,這篇文章提供了一個實用的視角,看看他們為什麼做出了轉變。
背景
我們是 Wafris,一家開源 Web 應用程式防火牆公司,除其他框架外,還提供 Rails 中介軟體客戶端。
在釋出時,v1 客戶端需要將本地 Redis 資料儲存與您的應用一起部署。我們現在釋出了使用 SQLite 作為後備資料儲存的 Rails 客戶端 v2。
本文介紹了我們從 Redis 遷移到 SQLite 時的決策、效能考慮因素和架構變更。如果您對我們為客戶(已部署的中介軟體)從 Redis 遷移到 SQLite 時的決策感興趣,請繼續閱讀本文
總結
- SQLite 有其優點,也有其缺點。
- Redis 有其優點,也有其缺點。
- 傳統的 RDBMS(Postgres/MySQL)有其優點和缺點。
這些資料儲存並非直接替代,如果您嘗試這樣做,您將會遇到麻煩。本文介紹了將基於 Redis 的 v1 客戶端重新架構為基於 SQLite 的 v2 客戶端時進行的測試和決策。
什麼導致了這一改變?
自 Wafris 成立的第一天起,我們的目標就是讓開發人員儘可能輕鬆地保護他們的網站。
但我們的 v1 在兌現這一承諾方面取得了好壞參半的結果。我們當時認為,用使用者擁有的(自帶的)Redis 資料儲存來支援 Wafris 客戶端是一個明智的選擇。
部分原因是我們是在 Heroku 生態系統中成長起來的,在這裡 Redis 只需點選一下即可啟動,並且部署方式也便於遠端訪問。我們還研究了 Sidekiq 等具有類似模型的成功專案。
但生態系統遠不止於此,我們的許多使用者都遇到了難以除錯和修復的 Redis 部署問題。
換句話說,如果我們試圖讓您輕鬆一些,我們不應該在此過程中隨便讓您成為 Redis 資料庫管理員。
什麼是速度?
儘管與傳統的 RDBMS 相比,Redis 很“快”,但它仍然是一個需要管理連線、記憶體、程序等的資料庫,這會給堆疊帶來更多的脆弱性(與我們想要實現的目標相反)。
最重要的是,如果您處於雲環境中,那麼您需要考慮網路延遲。網路延遲對我們來說是個大問題,因為必須根據 Wafris 中儲存的規則評估您應用的每個入站 HTTP 請求。因此,儘管我們付出了艱辛的努力和編寫程式碼以儘可能快地獲得 v1 客戶端,但我們經常會遇到這樣的情況:儘管我們盡了最大努力,但由於應用所配置的網路速度很慢,我們仍然會減慢應用的速度。
整體式假設
雖然確實存在完全分散式的應用程式,並且大多數 Rails 應用程式都是“龐大的整體”(tm?我不知道,不要起訴我),但我們發現很多分散式應用程式擾亂了我們的假設。
部署到多個區域的應用程式、將功能拆分為具有重疊職責的伺服器的應用程式或僅部分使用 Rails 並與其他語言或框架一起部署的應用程式。
大多數情況下,生產中的事情並不是那麼幹淨,這給使用 Redis 帶來了更多的摩擦。
迫使我們重新思考我們的架構
Wafris 是一款 Web 應用程式防火牆。在 Rails 中,它作為中介軟體安裝。它允許您設定“阻止 IP 1.2.3.4”之類的規則,然後當有人請求您的網站時,您會根據這些規則評估該請求。
想象一下這個簡化的兩步過程:
- 將 HTTP 請求與規則進行比較(如果匹配 == 403,否則為 200)
- 報告處理(阻止、允許、透過)
從抽象角度來說,這是對資料庫中規則的配對“讀取”(步驟 2),然後“寫入”報告,詳細說明對該請求及其資料所執行的操作。
從邏輯角度來看,這個過程的前半部分“讀”比後半部分“寫”重要得多:
- 讀取(又稱“請求”)需要按順序處理
- 必須對請求進行過濾,否則不良請求可能會透過
- 讀取(又稱“請求”)對時間敏感,因為它們會影響使用者感知的網站效能。
- 寫入(又稱“報告”)可以以較慢的速度、批次的、非同步的等等方式完成。
輸入 SQLite
其他人對 SQLite 的適用範圍的描述比我自己寫的更加詳細,因此關於這個話題,我將向您推薦以下資源:
Aaron Francis 的“高效能 SQLite”課程,網址為https://highperformancesqlite.com/
Stephen Margheim 的“SQLite on Rails”——如何以及為何實現最佳效能
Oldmoe- https: //oldmoe.blog/
SQLite 對 Wafris 有何好處?
如上所述,我們的主要瓶頸是網路 IO,Stephen 提到了 SQLite 文件中的這句話:“SQLite 不與客戶端/伺服器資料庫競爭。SQLite 與 fopen() 競爭。”
理論上,這應該比僅基於切斷網路往返的 Redis 解決方案快得多。
因此,我們決定對 SQLite 與 Redis 進行基準測試。
SQLite 和 Redis 的基準測試
基準測試是一門用高度精確的數字欺騙自己的黑暗藝術。
而對資料儲存進行基準測試則更加困難。我見過的每一個翻轉資料庫基準測試都被一層星號和限定詞所覆蓋,HN 上的評論充滿了“如果你在編譯時設定這個標誌,你的讀取速度就會提高 3%,而執行這個的人沒有這樣做這一事實證明他們得到了賄賂,並且他們積極出售瘋狂的遊艇搖滾 Harambe 模因的陰暗 NFT 騙局。
測試是在我的本地 Macbook Air M2 上進行的,並使用自制的 Redis 和本地 SQLite db 進行安裝。
- 我們針對現有範圍資料集(120 萬個條目)進行了測試
- 然後以相同的順序針對 SQLite 和 Redis 執行多組 IP。
- 在每個倍數下,我們都執行了 5 次測試並取平均值。
結果:
- SQLite 擊敗 Redis
與本地部署的 Redis 例項相比,SQLite 的速度大約提高了 3 倍。YMMV。再次注意,這是在考慮任何網路延遲之前。
從我們的角度來看,這是一個非常棒的結果,因為即使 SQLite 僅在本地與 Redis 相當,我們仍然能夠透過完全縮短網路時間而獲勝。
構建同步架構
在 v1(Redis)上,更新迴圈如下所示:
- 使用者在 Wafris Hub 中更新規則(“阻止 IP 1.2.3.4”)
- Wafris Hub 更新 Redis 資料儲存中的規則
這顯然不適用於 SQLite,因為我們無法將 SQLite 資料庫“推送”到 Web 伺服器。有一些較新的 SQLite 即服務提供商允許您執行此版本,但出於各種成本、效能和安全考慮,它對我們來說不起作用,因為我們仍然需要個人使用者來部署它們、開啟埠、允許入站連線等。
在 v2(SQLite)上,更新迴圈如下所示:
- 使用者在 Wafris Hub 中更新規則(“阻止 IP 1.2.3.4”)
- 每隔一段時間(時間或請求次數),客戶端會檢查更新的規則
- 如果規則更新,客戶端將下載一個全新的 SQLite 資料庫
這很有效,因為它消除了使用者的大部分安裝和配置責任。
我們發現 v2 客戶端的成功安裝量增加了約 3 倍。
總之
我們對使用 SQLite 的 v2 架構非常滿意。它已經幫助許多網站抵禦了攻擊並保持線上。
它變得更容易使用,我們需要的支援工作更少,使用者的麻煩也更少,我們認為這對於更安全、更有保障的網際網路來說是一個勝利。