Codis 的设计与实现 Part 2

本贴最后更新于 3284 天前,其中的信息可能已经时移世改

 

在 Codis 的设计中, Proxy 被设计成无状态的,客户端连接任何一个 Proxy 都是一样的。而且每个 Proxy 启动的时候,会在 Zookeeper 上注册一个临时节点, 所以客户端甚至可以根据这个特性实现 HA (其实我在豌豆荚内部就写了一个基于 Jedis 的 Codis HA RoundRobinPool)

当然,这个设计带来的好处是,请求可以被负载均衡,而且在整个系统中不会出现单点。 但是,问题来了,由于 Codis 是动态扩缩容的功能的, 当 Codis 在进行数据迁移的过程中,如何保证任意一个 Proxy 都不会读到老的或者错误的数据?

解释这个问题之前,我想先介绍一下 Codis 的数据存储方式和关于数据迁移的一些前置知识:

  • 数据被根据key,分布在 1024 个 slot 中, slot 是一个虚拟的概念,数据存储在实际的多个 codis-server (codis 修改版的 redis-server) 中,每个 codis-server 负责一部分key-value数据, 哈希算法是 crc32(key) % 1024
  • 数据迁移是由 codis-config 发起的,在 codis-config 看来,数据迁移的最小单位是 slot
  • 对于 codis-server 来说,没有任何分布式逻辑在其中, 只是实现了几个关于数据传输的指令: slotsmgrtone, slotsmgrt…. 其主要的作用是:随机选取特定 slot 中的一个 key-value pair, 传输给另外一个 codis-server, 传输成功后,把本地的这个 key-value pair 删除, 注意, 这个整个操作是原子的。

所以,这就决定了 Codis 并不太适合 key 少,但是 value 特别大的应用, 而且你的 key 越少, value 越大,最后就会退化成单个 redis 的模型 (性能还不如 raw redis),所以 Codis 更适合海量 Key, value比较小 (<= 1 MB) 的应用。

为什么 codis-server 的数据迁移是一个个key的,而不是类似很多其他分布式系统,采用 replication 的方式? 我认为,对于 redis 这种系统来说,实现 replication 不太经济, 首先,你需要 rdb dump 吧? 在 redis 里面所有的操作严格来说都是串行的(单线程模型决定),所以dump数据是需要 fork 一个新进程的, 否则如果直接 SAVE 会阻塞唯一的主线程,同时还得考虑dump过程和传输过程中产生的新数据的同步的问题, 实现起来比较复杂。所以我们每次只原子的迁走一个 key,不会把主线程 block 住, redis 操作的是内存,批量的一次性写入和分多次set几乎没有区别(对于单机而言), 而且这个模型还避免了迁移过程中的数据更新同步的问题,因为由于迁移一个 key 的操作是原子的, 对于这个 redis-server 来说, 在完成这次迁移指令之前,是不会响应其他请求的。 所以保证了数据的安全。

一次典型的迁移流程:

  1. codis-config 发起迁移指令如 pre_migrate slot_1 to group 2

  2. codis-config 等待所有的 proxy 回复收到迁移指令, 如果某台 proxy 没有响应, 则标记其下线 (由于proxy启动时会在zk上注册一个临时节点, 如果这个proxy挂了, 正常来说, 这个临时节点也会删除, 在codis-config发现无响应后, codis-config会等待30s, 等待其下线, 如果还没下线或者仍然没有响应, 则codis-config 将不会释放锁, 通知管理员出问题了) 相当于一个2阶段提交

  3. codis-config 标记slot_1的状态为 migrate, 服务该slot的server group改为group2, 同时codis-config向group1的redis机器不断发送 SLOTSMGRT 命令, target参数是group2的机器, 直到group1中没有剩余的属于slot_1的key

  4. 迁移过程中, 如果客户端请求 slot_1 的 key 数据, proxy 会将请求转发到group2上, proxy会先在group1上强行执行一次 MIGRATE key 将这个键值提前迁移过来. 然后再到group2上正常读取

  5. 迁移完成, 标记slot_1状态为online

关键点:

  1. 所有的操作命令,都通过 Zookeeper 中转,所有的路由表,都放置在 ZooKeeper 中,确保任意一个 proxy 的视图都是一样的。

  2. codis-config 在实际修改slot状态之前,会确保所有的 proxy 收到这个迁移请求。

  3. 在客户端读取正在迁移的slot内的数据之前, 会强制在源redis是执行一下迁移这个key的操作。

这两点保证了,proxy 在读取数据的时候,总是能在迁移的目标机上命中这个 key。

这就是 Codis 如何进行安全的数据迁移的过程。

转自:http://0xffff.me/blog/2014/11/11/codis-de-she-ji-yu-shi-xian-part-2/

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 脑图

    脑图又叫思维导图,是表达发散性思维的有效图形思维工具 ,它简单却又很有效,是一种实用性的思维工具。

    32 引用 • 99 回帖 • 1 关注
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    37 引用 • 157 回帖 • 3 关注
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    116 引用 • 54 回帖 • 3 关注
  • 单点登录

    单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    9 引用 • 25 回帖 • 1 关注
  • 工具

    子曰:“工欲善其事,必先利其器。”

    298 引用 • 763 回帖
  • 创业

    你比 99% 的人都优秀么?

    82 引用 • 1395 回帖
  • SVN

    SVN 是 Subversion 的简称,是一个开放源代码的版本控制系统,相较于 RCS、CVS,它采用了分支管理系统,它的设计目标就是取代 CVS。

    29 引用 • 98 回帖 • 690 关注
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    200 引用 • 120 回帖
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    70 引用 • 193 回帖 • 411 关注
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    107 引用 • 153 回帖
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    5 引用 • 18 回帖 • 181 关注
  • Shell

    Shell 脚本与 Windows/Dos 下的批处理相似,也就是用各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要是方便管理员进行设置或者管理用的。但是它比 Windows 下的批处理更强大,比用其他编程程序编辑的程序效率更高,因为它使用了 Linux/Unix 下的命令。

    125 引用 • 74 回帖
  • Git

    Git 是 Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

    211 引用 • 358 回帖
  • OpenStack

    OpenStack 是一个云操作系统,通过数据中心可控制大型的计算、存储、网络等资源池。所有的管理通过前端界面管理员就可以完成,同样也可以通过 Web 接口让最终用户部署资源。

    10 引用 • 3 关注
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖
  • Swagger

    Swagger 是一款非常流行的 API 开发工具,它遵循 OpenAPI Specification(这是一种通用的、和编程语言无关的 API 描述规范)。Swagger 贯穿整个 API 生命周期,如 API 的设计、编写文档、测试和部署。

    26 引用 • 35 回帖 • 1 关注
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖 • 2 关注
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    948 引用 • 1460 回帖
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 564 关注
  • 大疆创新

    深圳市大疆创新科技有限公司(DJI-Innovations,简称 DJI),成立于 2006 年,是全球领先的无人飞行器控制系统及无人机解决方案的研发和生产商,客户遍布全球 100 多个国家。通过持续的创新,大疆致力于为无人机工业、行业用户以及专业航拍应用提供性能最强、体验最佳的革命性智能飞控产品和解决方案。

    2 引用 • 14 回帖
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 447 关注
  • Ruby

    Ruby 是一种开源的面向对象程序设计的服务器端脚本语言,在 20 世纪 90 年代中期由日本的松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)设计并开发。在 Ruby 社区,松本也被称为马茨(Matz)。

    7 引用 • 31 回帖 • 247 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 29 关注
  • AWS
    11 引用 • 28 回帖 • 9 关注
  • GitBook

    GitBook 使您的团队可以轻松编写和维护高质量的文档。 分享知识,提高团队的工作效率,让用户满意。

    3 引用 • 8 回帖 • 1 关注
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    290 引用 • 4494 回帖 • 653 关注