最初发布在 bleacherreport.com
我们的 API 服务使用 Redis 作为缓存层。Redis 集合操作对于我们 API 服务所需的逻辑非常有用。不幸的是,我们在扩展 Redis 时遇到了一些问题。Redis 是一款单线程服务器,使用基于事件的范式读取传入连接,因此仅使用 1 个 CPU 内核。所以您可以垂直扩展 Redis,但水平扩展 Redis 非常具有挑战性。当我们的应用程序调用较重的 zset 和 zunionstore 操作时,就会出现这种情况。Redis 达到 CPU 限制,并被锁定在 100%。
我们还发现 Redis 将内存中的数据快照保存到磁盘的方式存在问题。Redis 派生另一个进程来保存数据,该进程使 Redis 的 RAM 占用量增加一倍。一旦 Redis 在框上耗尽内存,它就会变得非常慢。这实际上将您可以在框上使用的内存减少到实际可用内存的一半。在我们的案例中,我们使用 Redis 作为缓存,因此我们只是禁用了保存,以便我们可以使用框上的所有内存,并且一直在进行垂直扩展。但是,垂直扩展只会让你走这么远。我们目前的瓶颈是我们正在接近可用 CPU 的上限。
我们想尝试 Redis 集群,但开源版本仍处于开发阶段。 Redis 是开源 Redis 项目的主要贡献者之一,他们的平台已经实现了集群功能。 Redis 旨在自动无缝地扩展。Redis 数据库将在单个分片上扩展容量,并在需要时自动开始跨多个分片进行集群。所有这些都在幕后透明地进行。客户只需要管理一个简单的单一端点。
除了基本的基本健全性测试和功能测试外,我们还需要定量指标和性能指标来证明我们的迁移合法。
我们使用 em-proxy 将我们的服务器迁移到新的集群时进行蓝绿流量。这使我们能够将一部分流量代理到 Redis,对其进行测试,并在有限的曝光下对更改做出反应。
在那个晚上进行了一些谷歌搜索后,我遇到了 它,然后我在那个晚上使用单个实例进行了一些测试。然后在接下来的晚上,我创建了一个额外的测试集群,这大约需要 5 分钟,然后将来自实时生产集群的**所有**流量都定向到测试集群,并让它运行整夜和第二天。这种技术强大的地方在于,我们不会用输入基准数据来猜测,而是实际使用实时生产流量。最重要的是,我们可以实时比较New Relic 数据集。
结果令人难以置信。
左侧图表基于我们内部维护的 Redis 服务器。右侧是连接到 Redis 的测试集群。集群之间唯一的区别是,一个使用开源 Redis 服务器,另一个使用 Redis。在使用标准开源 Redis 服务器时,我们会看到响应时间间歇性地飙升至 700 毫秒,平均为 435 毫秒;它无处不在。 Redis 使我们的响应时间达到一致且平滑的平均 55 毫秒!无论 Redis 在施展什么巫术,它显然都有效。
在我们的测试过程中,我们发现 Redis 禁用了一些 Redis 命令,因此需要对我们的 API 代码进行一些更改。
例如,Redis 禁用了object
命令。
下一个错误是由于 Redis 正在分片,但我们的应用程序没有准备好处理它。
要解决此问题,您需要命名 Redis 密钥,以便 Redis 可以管理数据分片。密钥需要用大括号命名,例如hello{dynamic}world
。因此,以下密钥映射到不同的分片
这里有更详细的解释:/kb/redis-cloud-cluster。我们最终部署到单个分片,这与我们之前的环境相同,并将稍后回到分片。
这种测试方法非常强大。我们在实际在生产环境中推出 Redis 之前发现了很多问题并进行了修复。如果我们改为将所有流量迁移到 Redis,我们将陷入救火状态,并且可能回滚,而没有意识到 Redis 提供的巨大性能优势。
Redis 非常快!如果您仔细阅读,您可能已经意识到了关键所在。我们从 Redis 中获得了这种性能提升,甚至没有进行分片。我们还有更多后续工作要做,包括分片,这应该会更显着地提高我们的性能。如果您正在使用 Redis,并且在将其扩展到单个 CPU 之外或遇到内存受限时遇到问题,那么 Redis 是一个不错的选择。