一、背景
(一)当前为了后端网络程序的高并发和高可用,总是需要多台服务器一起协调工作,它们可能负责不同的模块(属于分布式),也可能多台提供相同的功能(属于集群)。
(二)为了解决读写分离的主从架构的数据库同步问题,需要数据库支持集群和同步。
(三)为了让请求均匀合理的分摊到每台服务器处理,需要解决负载如何均衡的问题(一般用nginx代理和分摊请求)。
二、本文目的
探讨多台数据库服务器如何来数据同步,以及设计简单的网络同步协议。
三、多台数据库的连接方式
(一)主从分离方式
1、根据实际的平均请求量,可能大多数是读取数据库记录,少数是更新数据库记录;也有可能相反。
需要综合查询耗时,更新耗时,操作平均类型数量占比来分析和决策(没差别可以不分离)。
2、因为平时大部分用户可能只是调用数据库的查询功能,只有少部分才调用更新功能(新增、删除、更新)。
3、设计应用程序时根据功能选择对应的数据库执行。
4、更新数据库会和每个查询数据库建立连接,发送最新的更新记录进行更新。
(二)设计数据库的链式结构
1、指的是每台数据库除了和应用服务器建立网络连接外,还设计数据库的串联链式网络结构。
2、链式结构指的是一个接一个连在一起,构成一条线。
3、可能用来更新的数据库在第一个,查询的数据库都接在后面。
4、我觉得优点是每相邻的两个数据库有建立双工的通信网络;
5、当信息同步时,只需要第一个更新数据库把更新的记录传给下一台数据库,然后继续传给下一台,最后每一台都获得最新的数据更新。
6、每一台查询数据库获取更新记录后,进行更新,还要反馈结果给上一台库,进行重发,然后重新更新。
7、要注意时间戳,防止重复更新。
8、缺点是容易断链,导致后面联系不通,无法更新。
(三)设计星型的连接方式
1、除了和应用系统有网络连接,每个数据库还和一台中心交换服务器建立双向网络连接。
2、更新时由更新数据库发送最新记录给中心交换服务器。
3、中心交换服务器会把最新记录发给每台查询数据库进行更新。
其他:如果用交换机或者路由器把数据库连接在一起,还可以采用UDP协议的网关广播方式来同步最新数据。缺点是不可靠,需要实现可靠机制。
四、发现数据库的记录更新的机制
(一)日志记录
数据库有日志,当执行更新操作时会写入对应的SQL语句,用一个后台进程不断的扫描和监听就能知道记录发生更新,就能进行同步操作。
该机制方便用户的使用,能自动发现更新,自动同步。
(二)应用层面的主动更新
如果用户提交更新操作后,在执行时,同时把该操作在查询数据库中操作,这样可能会增加时间。
改进方式为:把同步操作提交给消息队列后返回结果给用户,查询数据库获取消息后执行。
五、猜测监听数据库更新日志的思路
(一)第一种、主动循环扫描方式
进入循环(退出为假):
1、获取日志的最新修改时间。
2、和当前日期比较,判断是否改变。
3、如果改变,跳跃到上次的文件指针位置,开始读取日志中的更新记录,直到末尾;
处理后开始同步给其他数据库。
记录最新的文件指针读取位置。
4、如果没有改变,休眠几毫秒,继续循环。
(二)第二种、事件触发方式
1、当数据库执行到更新语句,并且产生了更新日志,就开启一个线程或者进程来同步。
2、开启的进程或者线程执行逻辑和第一种方法的循环体逻辑一样,不需要循环,执行同步后就退出该异步线程或者异步进程。
六、设计一个同步数据库记录的网络协议格式
(一)文本格式(适合SQL语句)
1字节开头符
2字节发送者标志
8字节发送时毫秒数
2字节保留符
任意长度的SQL语句字符
1字节ASCII码为0的结尾符
(二)二进制格式(特殊形式,传输表的字段值)
1字节操作类别(插入、修改、新增)
2字节发送者标志
8字节发送时的毫秒数
任意长度的数据库名字组成的字节
1字节值为0的字节(间隔符)
任意长度的表名组成的字节
ASCII码为0的字节(间隔符)
2字节数据长度
指定长度的记录负载(UTF8或者GBK格式)
(三)同步结果(通用的)
1字节类型(执行结果,成功为1,失败为0)
2字节保留
2字节影响记录数
1字节文本长度值
指定长度的执行结果文本信息
1字节结尾符(一般为字节0)
七、查询数据库收到更新信息的反应
1、监听同步网络连接的线程阻塞等待。
2、收到同步网络数据,读取到内存。
3、调用执行方法执行SQL语句。
可能需要控制事务。
4、按照结果协议格式回复执行结果。