Codis 的设计与实现 Part 1

最近开源了 Codis,在 Github 上的反响挺不错的,3天已经收集到了 1000 多 stars, 让我比较吃惊。 也从侧面说明了确实分布式缓存是大家都会遇到的问题。于是我打算在本篇和接下来的几篇 Blog 详细说明一下 Codis 的设计和一些背后的考虑,以及对于分布式存储(尤其是缓存)系统的一些思考。

Why proxy?

Codis 的架构采用了 Proxy-based 的设计,没有走官方 Cluster 的路,官方的 Cluster 实现是 P2P 的模型,依靠 Gossip 协议进行消息同步和将数据分若干个 Slot 作为管理的单位,客户端需要更改。这个模型的好处是:

  • 真正的无中心节点
  • 对于客户端来说请求的性能不会损失太多

但是缺点同样明显:

  • 状态很难明确,你很难清楚的知道集群现在处于什么状态
  • 对与redis来说,集群的升级困难,运维困难,因为它将分布式的逻辑和存储引擎绑定在了一起。
  • 需要依赖 smart client

这两个缺点几乎在任何 p2p 模型的分布式系统中都存在,由于第一个问题,导致开发和调试的过程也异常艰辛(官方的 cluster 几乎写了 3 年才比较稳定)

而 Proxy-based 的方式的好处就比较明显了:

  • 开发成本低
  • 业务的切换成本低
  • Proxy 的逻辑和存储的逻辑是隔离的

所以,在 Codis 之前,Twemproxy 是这个方案的最优的选择,应用也非常广泛,许多大型的互联网公司都在使用它,但是 Twemproxy 也有它的问题, 最大的问题是:Twemproxy 真的就只是一个 Proxy 而已, 集群的功能完全没有。而且看上去 Twitter 也不打算继续维护它了。
Twitter 最近的一个 Talk,提到了Twitter 内部对于 Scaling Redis 的一些做法和想法,其中对于 Proxy 的方案是比较推崇的(同时也提到了他们内部也不再使用 Twemproxy 了….),里面理由写得比较清楚了,有兴趣的可以去看看。同样的, Facebook 之前那篇关于扩展 memcached 的论文也提到了类似的方案 (mcrouter)。其中我觉得这个方案背后最重要的思想就是:存储和分布式逻辑分离。至于因为转发请求而损失的性能,可以通过其他的方式补回来, 比如水平扩展 Proxy。带来的好处是整个系统的状态非常清晰,几乎所有组件都可以独立的部署和升级,程序还比较好写,所以 Codis 从一开始就坚定的走 Proxy 这条路。

但是相对于 Twemproxy, Codis 又有一些改进,首先集成了集群的功能,使用 Presharding 对分散数据的存储。所有的集群状态信息依赖 ZooKeeper 进行同步, 所有的 Proxy 是无状态的。这样就可以实现多 Proxy 的水平扩展。
另外一个比较重要的决定是使用 Go 作为主要开发语言,抛掉信仰问题不谈 (我和 @goroutine 都是 go 的脑残粉), go 几乎就是针对这种后端的网络程序而发明出来的语言,这给开发工作带来了极大的效率提升,从写下第一行代码,到第一个可用版本,几乎才用了不到一个月的时间。

当然,使用多 Proxy 对于迁移过程中数据一致性带来一些问题,会在下一篇 blog 介绍一下 Codis 是怎么解决的。

本文来自:dongxu.h

感谢作者:c4pt0r

查看原文:Codis 的设计与实现 Part 1

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。