概念

MTS

Multi-Threaded Slave,并行复制(代码里常用的缩写)
在Slave重现Relay Log时,由单线程分发event,由多线程并行执行event的特性

Coordinator/Worker

event的分发/执行线程

Group

group代表由一系列event组成的事务(在rpl_rli.h的注释中),对其中event做如下分类(在log_event.cc的注释中):

  • B-event:起始event,Query_log_event的BEGIN事件
  • g-event:包含信息(db_name,table_name等)可以用来计算分发给哪个Worker,Table_map、Query_log_event等
  • p-event:一般放在g-event前,如INTVAR_EVENT、RAND_EVENT、USER_VAR_EVENT、BEGIN_LOAD_QUERY_EVENT、APPEND_BLOCK_EVENT
  • r-event: 一般放在g-event后,如Delete, Update等“regular” event
  • T-event:结束event,XID, COMMIT, ROLLBACK, auto-commit query

    约束

    并行复制需要满足两个约束来保证Master/Slave上的数据一致性:
    [约束1] 一个DB的不同事务分配给一个Worker线程
    [约束2] 一个事务涉及到多个DB,则这些DB的操作都需要分配给同一个Worker线程

    实现

    并行复制的总体流程如图

聚焦于函数Log_event::get_slave_worker,函数将event分发到Worker,返回这个Worker的指针

代码中的变量说明

  • curr_group_assigned_parts(CGAP):当前Group的映射关系
  • Assigned Partition Hash(APH):[TO-DO]
  • GAQ:Master binlog的顺序执行序列

    逻辑

    如果是B-event,p-event

    表明是事务的开始,将event加入curr_group_da,表明会在延迟分配,返回Worker为NULL
    (curr_group_da:deferred array to hold partition-info-free events)

    如果是g-event

    g-event中包含分发Worker的信息,由map_db_to_worker实现:
    [参数]

  • dbname,作为Hash的Key

  • last_worker:当前Group上一次分配的Worker(给该event前的g-event分配过的Worker)

[步骤]

  • 当前的Group之前已经分配过相同的db_name(在curr_group_assigned_parts,CGAP中查找),直接返回last_worker(约束2
  • CGAP中没查找到,在APH中查找(在Relay Log之前Group中是否有该event的映射关系):
    • 返回NULL:使用分配一个Worker,生成映射关系,并插入到APH中
    • 返回的Worker没有被Group使用(entry->usage == 0):说明之前没有Group中的event映射过该event,直接将该event映射到last_worker(如果last_worker为NULL,使用get_least_occupied_worker分配一个Worker)
    • 返回的Worker == last_worker:直接使用last_worker(约束1
    • 返回的Worker != last_worker:event映射冲突,需要等待引用该映射关系的Group执行结束,再将event映射为last_worker(约束1

      如果是r-event, T-event

      返回该Group已分配的Worker(lastassigned_worker)[TO-DO]_

      表级并行复制

      map_db_to_worker函数的声明为:
      由以上的分析,函数中会将dbname作为Hash的Key来分配Worker,只需要将dbname修改为dbname(数据库名)+tablename(表名)就可实现表级并行复制