重新架构:从 Redis 到 SQLite 性能提升

时间:2024-10-25 09:22:42

在这篇博文中,他们用 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”之类的规则,然后当有人请求您的网站时,您会根据这些规则评估该请求。

想象一下这个简化的两步过程:

  1. 将 HTTP 请求与规则进行比较(如果匹配 == 403,否则为 200)

  2. 报告处理(阻止、允许、通过)

从抽象角度来说,这是对数据库中规则的配对“读取”(步骤 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 进行安装。

  1. 我们针对现有范围数据集(120 万个条目)进行了测试
  2. 然后以相同的顺序针对 SQLite 和 Redis 运行多组 IP。
  3. 在每个倍数下,我们都运行了 5 次测试并取平均值。

结果:

  • SQLite 击败 Redis 

与本地部署的 Redis 实例相比,SQLite 的速度大约提高了 3 倍。YMMV。再次注意,这是在考虑任何网络延迟之前。

从我们的角度来看,这是一个非常棒的结果,因为即使 SQLite 仅在本地与 Redis 相当,我们仍然能够通过完全缩短网络时间而获胜。

构建同步架构
在 v1(Redis)上,更新循环如下所示:

  1. 用户在 Wafris Hub 中更新规则(“阻止 IP 1.2.3.4”)

  2. Wafris Hub 更新 Redis 数据存储中的规则

这显然不适用于 SQLite,因为我们无法将 SQLite 数据库“推送”到 Web 服务器。有一些较新的 SQLite 即服务提供商允许您执行此版本,但出于各种成本、性能和安全考虑,它对我们来说不起作用,因为我们仍然需要个人用户来部署它们、打开端口、允许入站连接等。
在 v2(SQLite)上,更新循环如下所示:

  1. 用户在 Wafris Hub 中更新规则(“阻止 IP 1.2.3.4”)

  2. 每隔一段时间(时间或请求次数),客户端会检查更新的规则

  3. 如果规则更新,客户端将下载一个全新的 SQLite 数据库

这很有效,因为它消除了用户的大部分安装和配置责任。
我们发现 v2 客户端的成功安装量增加了约 3 倍。

总之
我们对使用 SQLite 的 v2 架构非常满意。它已经帮助许多网站抵御了攻击并保持在线。
它变得更容易使用,我们需要的支持工作更少,用户的麻烦也更少,我们认为这对于更安全、更有保障的互联网来说是一个胜利。

https://www.jdon.com/75708.html