2014-12-02

SSDB源码分析 – 主从和多主同步原理解析

Views: 114701 | 53 Comments

SSDB 的主从同步策略非常简单, 就是把主(Master)上的所有写操作(Binlogs), 在从(Slave)上再执行一遍. MySQL 的主从同步也是一样. 而多主可以理解为互为主从.

把 Master 上的所有操作(Binlogs)在 Slave 上执行一遍, 说来很简单, 但还是会遇到一些难题, 例如 Binlogs 不可能无限地永久保留. SSDB 只保留最新的 1000 万次写操作. 对于熟悉 MySQL 的同学可能也知道这样的例子: 在有 Binlogs 之前, 数据库内已经有了一部分数据. 也就是说, 这部分数据是无法通过 Binlog 来获得的.

为此, 要有一个基础数据的拷贝(Copy)过程. 对于 MySQL 来说, 必须由 DBA 手动拷贝. 而对于 SSDB 来说, 这是自动的.

COPY 状态

因为 Copy 过程不是立即完成的, 所以如何处理 Copy 过程中的新的 Binlog 又成为一个问题. 当然, 问题也很容易解决. 不过, 在解决之前, 要先了解 SSDB 的 Copy 过程.

SSDB 数据库中的所有数据都是排好序的, 所以你可以把整个数据库理解为一个链表, SSDB 从表头开始 Copy, 一次一个节点, 游标一直往后. 这时, 如果有新的 Binlog, SSDB 会先判断这条 Binlog 对应的节点在链表中的什么位置, 是在游标的前面还是后面?

如果在游标的前面, 那么会把这条 Binlog 发给 Slave 执行. 如果在游标的后面, 就会直接忽略掉, 因为游标最终会移动到更新的位置. 从这个描述也可以知道, 处于 Copy 阶段的 Slave, 有可能无法立即知道 Master 上的更新.

当游标移动到了链表的末端之后, Copy 过程就结束了, 主从同步流程进入到 Sync 阶段, 也就是即时(毫秒级)更新阶段.

SYNC 状态

Sync 其实非常简单, 就是 Master 每收到一条写指令, 就把这条指令发给 Slave 执行.

Master 会把 Binlog 进行编号(序号), 所以, Slave 在重启之后是可以断点续传的. 因为有序号的原因, Master 上就可以看到 Binlog 最大序号(用 ssdb-cli 执行 info 命令可以看到 binlogs.max_seq):

binlogs
        capacity : 10000000
        min_seq  : 113033
        max_seq  : 113055

而在 Slave 上, 就能看到当前已经收到的 Binlog 的序号(replication.slaveof.last_seq).

replication
    slaveof 127.0.0.1:8888
        id         : svc_2
        type       : sync
        status     : INIT
        last_seq   : 113055
        copy_count : 0
        sync_count : 0

Master 上的 binlogs.max_seq 应该和 Slave 上的 replication.slaveof.last_seq 相等, 不然说明有一部分更新还没有来得及同步. 注意: 这两个数据是在不同的服务器上获取的!

如果在 Master 上用 info 命令查看, 你还会看到这样的信息:

replication
    client 127.0.0.1:55158
        type     : sync
        status   : SYNC
        last_seq : 113055

这是从 Master 的角度看, 当前连接上来的 Slave 的信息, replication.client.last_seq 一般是和 replication.slave.last_seq 是相等的. 注意, 这两个数据是在不同的服务器上获取的!

关于 slaveof.type 同步的类型

  • 对于主从同步, Slave 上的 ssdb.conf 中的 slaveof.type 必须配置成 sync.
  • 对于双主或者多主, 所有的服务器的 ssdb.conf 都必须将 slaveof.type 配置成 mirror!

对于双主或者多主, 如果不配置成 mirror 会出现什么情况? 那就是死循环! 一条 Binlog 会在所有服务器上不停地来回传递放大.

关于 slaveof.id

你必须知道, SSDB 节点是不知道自己的 ID 的, 你没法配置节点的 ID.

至于配置文件中的 replication.slaveof.id, 假设是在服务器 B 上的配置, B 想从 A 同步数据, 是指 B 认为它所连接的 A 的名字叫 id, 至于 A 叫什么(A 其实没有名字), 这没关系.

事实上, 这个 id 是为了标识一个数据库, 而不是一台机器, 无论这个库你把它拷贝到哪台机器上跑都没关系. B 只认这个库, 即使你把它迁移到了另一台机器, B 仍然认得, 不会认错, 还是会继续从上一次的断点继续同步.

Related posts:

  1. SSDB 的双主和多主配置
  2. MySQL 在线增加从库
  3. SSDB 配置文件
  4. MySQL 数据库双主配置
  5. SSDB源码分析 – 服务器的启动过程
Posted by ideawu at 2014-12-02 20:02:42

53 Responses to "SSDB源码分析 – 主从和多主同步原理解析"

  • 问一下SSDB做主从同步的binlog以及同步偏移量在重启后会丢失吗?以及对传输网络中断有考虑吗?因为现在考虑使用它做比较远距离机房的同步。 Reply
    @wang: 可以断点续传. Reply
    @ideawu: 再问一下,这个binlog文件名是什么?在data下没有看到类似的文件名。 Reply
    @ideawu: 不好意思,找到了,是LOG文件把。 Reply
    @wang: 不是, 是后缀为binlog的文件 Reply
  • 你好,问一下,会不会出现master向slave重复推送了同一条binglog?slave那边有做去重的判断吗? Reply
    @netfocus: ssdb 通过序号机制避免这种情况的发生? 如果你比较关心原理的话, 你可以尝试阅读源码. Reply
  • 你好,貌似现在主从配置只能通过配置文件,不知可以通过命令进行管理?
    不可以的话,后续是否有计划增加此命令支持呢?
    谢谢! Reply
    @cxz: 暂时还没有此计划. 对于多主架构来说, 动态的增加节点是一个复杂的过程. 而对于一主多从, 增加从节点时不需要修改主的配置文件. 频繁的变更slave的指向, 应该是比较罕见的应用场景. Reply
    @ideawu: 明白了,谢谢!
    主要是想利用自动检测,有问题时使用命令将slave转为master。
    目前看样子可以使用双主结构替代。 Reply
  • 问一下,200G的数据,是用一个SSDB来存储读取性能好,还是散列成10个SSDB,每个SSDB负责20G数据存储读取性能好?(假设各项cache都是一样的比例) Reply
    @wang: 单纯说性能,应该是分开好,但是,你这样带来了系统的复杂度和维护成本的上升,所以应该考虑的是性价比 Reply
    @liaohongliu: 是的. Reply
  • 相对于 mongodb来说,ssdb的优势是什么呢? Reply
    @alice: mongodb 消耗内存达到了霸道的程度,相比ssdb,则温和很多 Reply
  • 您好,请教您一个关于SSDB服务器动态扩容的问题。之前数据都在一台服务器上存储,后来添加了一台机器,我采用Hash算法把数据分配到两台机器上,但一直没想到好的方案去判断某个key存储在哪台服务器上 Reply
    @soo: 如果你是根据 hash 算法分配数据, 那么也是通过同一个 hash 判断某个 key 在哪台服务器. Reply
  • 您好,redis每个方法都有复杂度显示,您能否加上这个呢,比如GET(O(1))之类的,还有就是,内存和总key数的配比,大概什么比例性能最高,谢谢~ Reply
    @binger: 其实命令复杂度较高的主要是zset中的zrange/zrank等基于位置的, 其他还好, 另外配比应该跟进你的数据读取特点来配比 Reply
  • 想问一下,hset如何设置失效时间呀。 Reply
    @wangchun: hi, 目前不支持 hset 设置失效时间. Reply
    @ideawu: 哦,那 $ssdb->keys(‘a’, ‘z’, 10); 第一个参数,不是代表说 key的开始字母是a,结束字母是b , 例如 key = "accccccb", 能被查询到, 它不支持通配符查询??? Reply
    @wangchun: 仅支持前缀搜索. Reply
    @ideawu: 这个命令真心难用 Reply
    @ideawu: 前缀搜索支持几个字符呢? 我这样 keys "avail_trip" "" -1

    tax_route 开头的字符也会返回来 Reply
    @wangchun: keys根据前缀的*范围*(start, end)进行搜索. 空表示不限制前缀. 具体需要仔细看文档: http://ssdb.io/docs/zh_cn/php/
  • 你好,我有两个问题,
    1.问下是否可以理解成主从模式下,从是readonly,不能接受写?
    2.双主模式下,两个都可以写,相互间的复制方式也还是类似主从的方式? Reply
    @wangshuai:
    1. 跟 MySQL 主从一样, 不限制在从上的写, 但计划中会加上 readonly 模式.
    2. 是的. Reply
    @ideawu: 多谢,另外一个问题,你在官网上写SSDB所用内存的最大大小为cache_size + write_buffer_size * 66 + 32,我的理解是cache_size指的是leveldb的block cache,write_buffer_size指memtable的大小,但这个数量66是不是因为level0的sst文件最大数量为64,所以最多只能有65个immutable memtable?还有后面的32M指的是什么占用的空间了? Reply
  • 你好,我想问下,slave是怎么同步master的数据的?是master push的方式,还是slave去拉取的方式?另外,想问下,copy的过程具体是怎样的,是一条一条数据同步么? 同步的过程,是否参数可以干预同步速度的? Reply
    @liaohongliu: 是推的方式. ssdb.conf 中的 sync_speed 参数可以限制速度. Reply

« [1][2] » 2/2

Leave a Comment