DCache-CacheServer分析(八)

本文介绍CacheServer的主从节点是如何进行binlog同步的,涉及到MKBinLogTimeThread和MKBinLogThread 2个线程。

概述

为保证存储的可靠性,Master节点会同步将本次数据操作(如set/delete)记录到binlog文件中,然后迅速将binlog同步到Slave节点,以保证多节点数据的最终一致性。

DCahce的binlog同步是由Slave发起的,调用Master的rpc方法拉取binlog并记录到本地。Slave每次写完本地binlog后,都会将本次同步的时间点写入sync_time.data文件中,用于评测主从同步质量(数据同步的时间差超过300ms会禁止主从切换);将本次同步过来的binlog文件名和指针位置写入sync_point.data中。后续,Slave无论是正常处理还是异常恢复,都会从sync_point.data中读取当前同步的文件名和指针位置,调用Master的服务继续同步binlog。

记录binlog同步时间点(sync_time.data)和同步位置(sync_point.data)分别由线程MKBinLogTimeThread和MKBinLogThread线程来完成的。下面分别介绍下这2个线程。


MKBinLogTimeThread

功能:获取备份源最后记录binlog时间的定时类。

该线程在CacheServer初始化时启动。

文件:

MKBinLogTimeThread.h

MKBinLogTimeThread.cpp

配置解析

#保存synctime文件的间隔(秒)

SaveSyncTimeInterval=10

每隔SaveSyncTimeInterval秒记录一次binlog同步时间点到sync_time.data中。

Master的处理流程

每隔100ms上报一次binlog的同步时间差到Dcache的OptServer,用于监控主从同步质量。

Slave的处理流程

  1. 初始化BinLogObj服务的代理;
  2. 线程启动时从文件sync_time.data中获取当前同步时间(g_binLogSyncTime.tSync)和上一次同步时间(g_binLogSyncTime.tLast);
  3. 休眠3秒,防止同步binlog线程还没有同步binlog 而上报同步差异;
  4. 线程循环开始,每隔500ms执行一次该线程;
  5. 距上次保存sync_time.data时间超过阈值(SaveSyncTimeInterval)时,再次保存 sync_time.data;
  6. 如果处于备机恢复状态(g_app.gstat()->isSlaveCreating()),则休眠100ms,回到4;
  7. 如果Master(备份源)地址发生变化,则重新创建BinLogObj服务的代理,更改binlog源。
  8. 如果没有主节点了,则上报binlog的同步时间差,休眠100s,回到4;

  9. 调用BinLogObj服务的getLastBinLogTime方法,获取备份源内存中最后记录binlog的时间;
  10. 更新备份源的binlog最新记录时间到本地的内存(g_binLogSyncTime.tSync和g_binLogSyncTime.tLast)中;
  11. 上报binlog的同步时间差,回到4;

MKBinLogThread

功能:Slave向Master(备份源)发起请求,拉取binlog。

该线程在CacheServer初始化时启动。

文件:

MKBinLogThread.h

MKBinLogThread.cpp

配置解析

涉及到配置文件中的信息如下:

<BinLog>
    #binlog日志文件名后缀
    LogFile=binlog
    #每次同步binlog的行数
    MaxLine=10000
    #是否记录binlog
    Record=Y
    #是否记录key binlog
    KeyRecord=N
    #主备同步使用key binlog
    KeySyncMode=N
    #同步binlog是否开启压缩
    SyncCompress=Y
    #采用gzip压缩格式
    IsGzip=Y

    #备机同步binlog缓存buffer的szie
    BuffSize=10
    #保存synctime文件的间隔(秒)
    SaveSyncTimeInterval=10
    #active binlog产生的周期(秒)
    HeartbeatInterval=600
</BinLog>

<Cache>
    #insert一个数据是在主key链的头部还是尾部,Y/N -- 头/尾
    InsertOrder=N
    #数据更新时,同时更新主key链下的顺序
    UpdateOrder=N
    #主key最大记录条数限制,只在无源cache时有效,超过最大记录限制将删除旧的数据,0表示无限制
    MkeyMaxDataCount=0
</Cache>

<DbAccess>
    #是否存在DB,Y/N
    DBFlag=Y
    #DbAccess的obj名称
    ObjName=DCache.TestDbAccessServer.DbAccessObj
    #当Cache中没有数据时,是否从DB或文件查询, Y/N
    ReadDbFlag=Y
</DbAccess>

线程读取的配置:

MaxLine,每次同步binlog的最大行数

LogFile

SyncCompress

Record

KeySyncMode

BuffSize

InsertOrder

UpdateOrder

MkeyMaxDataCount

ReadDbFlag,如果配置为Y/y,则MkeyMaxDataCount重置为0(无数量限制)

DBFlag,Slave是否写binlog文件

正常情况下我们采用默认配置即可。

可能会修改到的配置是BuffSize。当binlog的队列中数据量大于该值时,会提示:

[MKBinLogThread::syncBinLog] queue is full!

并结束本次同步。我们可以通过修改这个值来增加binlog缓存。

处理流程

会启动2个线程:

  1. run线程,写binlog线程队列,并更新binlog的时间;
  2. WriteData线程,从binlog线程队列中取出数据写入binlog文件。

Slave处理流程

run线程:

1.初始化binlog服务代理

2.循环处理(100ms)

3.如果为备机恢复状态(SlaveCreating.dat),则休眠100ms,再次执行2;

5.从sync_point.data文件中获取binlog的文件名称以及指针位置;

6.确认备份源地址(一般情况下都是Master)是否有变化,有变化则重新获取;

7.执行binlog同步;两种同步方式:压缩同步(syncCompress)和正常同步(syncBinLog);

syncBinLog:

  • binlog线程队列中的数据量大于阈值(BuffSize配置)时,结束同步,回到2;
  • 调用主节点的 BinLogObj服务getLog;
  • 更新binlog的时间(这里只更新了内存中的值);
  • 写入binlog线程队列_binlogDataQueue,重置指针位置的值(内存中);

syncCompress:

  • SyncCompress=Y/y时调用
  • 与syncBinLog流程基本一致,调用BinLogObj的getLogCompressWithPart服务;
  • 获取经过压缩的Binlog日志,如果返回的数据超过8M,会分块返回;

WriteData线程:

1.循环开始

2.binlog线程队列_binlogDataQueue中有数据时,pop取出;如果没数据,休眠100ms回到1;

3.如果是压缩同步,则解压;

3.写binlog(MKBinLogThread::wirteBinLog)

  • 如果binlog类型是 BINLOG_ACTIVE,则跳过 (保活日志,确保每个小时都有binlog生成);
  • 将binlog数据写入内存;如果接了db,就进行相应处理(g_HashMap);
  • 如果Record配置为Y/y,则将binlog内容写入磁盘文件;

4.保存binlog的文件名以及已经同步的指针位置到文件sync_point.data中。

Master处理流程

run线程:删除sync_point.data文件,休眠100ms,再次执行。

WriteData线程:Master节点由于binlog队列中没有数据,休眠100ms,再次执行。

为什么是100ms就扫描一次?

由于网络故障而发生主从切换时,原来的Master(现在变成了Slave)恢复服务后,就可以立即进入Slave状态、进行binlog同步。


总结

DCache在做binlog同步时,由CacheServer启动2个独立的线程进行处理,由Slave调用Master的服务同步binlog。将同步时间点记录到sync_time.data文件中,用于判断主从同步质量;将当前同步的binlog文件名以及文件中的指针位置记录到sync_point.data文件中,用于“断点续传”。

 

DCache使用的是“同步刷盘,异步复制”的策略,非强一致性。但是其默认100ms的同步周期(这个值是写死的)将主从数据差异控制在了一定范围内。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
写回缓存是一种缓存机制,它将数据暂时保存在缓存中,只有在需要时才写回到主存储器中。这种机制通常用于提高数据读取和写入的效率,并减少对主存储器的访问次数。 在计算机系统中,缓存分为指令高速缓存(Instruction Cache,简称ICache)和数据高速缓存(Data Cache,简称DCache)两种类型,它们分别用于缓存指令和数据。因此,在实现写回高速缓存时,需要同时考虑ICache和DCache。 具体实现步骤如下: 1. 当CPU需要读取数据时,首先在ICache和DCache中查找缓存。如果能够命中缓存,则直接从缓存中读取数据,否则需要从主存储器中读取数据。 2. 当CPU需要写入数据时,将数据写入DCache中的缓存中,同时标记该缓存块为“脏块”,表示该数据已经被修改过。如果该缓存块已经存在于ICache中,则也需要将其标记为“脏块”。 3. 当CPU需要从DCache中写回脏块时,将该数据写回到主存储器中,同时将该缓存块标记为“干净块”。 4. 当CPU需要从ICache中写回脏块时,需要将该缓存块先写回到DCache中,再将其写回到主存储器中。 需要注意的是,写回高速缓存机制需要进行一定的控制,以保证数据的一致性和正确性。例如,在写回脏块时,需要遵循一定的写回策略,例如先写回最近最少使用的缓存块,或者先写回最早被修改的缓存块等等。同时,需要处理好多个CPU同时访问高速缓存的情况,以避免数据冲突和竞争问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员柒叔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值