会员中心
用户名:
密 码:
 
  忘记密码
邮政通信
MySQL数据复制功能在邮政计算机系统中的应用
文章来源:本站原创  发布时间:2014-10-31  浏览次数:596
作者:杨瑞启
(辽宁省邮政公司信息技术局 110013)
摘要:MySQL的数据同步功能,使得分散在各台服务器上的数据以数据重做的方式得以同步,从而达到信息完整的效果。本文针对邮政公司业务网点前置系统运维中出现的复制功能问题进行解析,并对该复制功能的进一步完善进行讨论。
关键词:MySQL,数据复制,负载均衡
1.MySQL数据复制功能
      本文中提到的复制功能,是MySQL在3.2版本以后提供的单向、异步的数据同步功能。在复制过程中,一台服务器充当主服务器,而一台或多台其它服务器充当从服务器。主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环。这些日志可以记录发送到从服务器的更新。当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位置。从服务器接收从那时起发生的任何更新,然后封锁并等待主服务器通知新的更新。
1.1 MySQL复制功能的原理
      MySQL的复制不是把主服务器上的数据直接复制一份传到从服务器上,在MySQL的英文手册中,该功能叫做“replication”,字面上讲,就是重作的意思。说的直白一点,就是主服务器上做了哪些操作,从服务器按照同样的步骤照做一遍,以达到和主服务器数据一致的效果。
      因此,当主服务器有更新的时候,主服务器会把更新操作的SQL写入二进制日志(Bin log),并维护一个二进制日志文件的索引,以便于日志文件轮回(Rotate)。在从服务器启动异步复制的时候,从服务器会开启两个IO线程,其中一个线程连接主服务器,要求主服务器把二进制日志的变化部分传给从服务器,并把传回的日志写入本地磁盘。另一个线程则负责读取本地写入的二进制日志,并在本地执行,以反映出这种变化。
1.2 MySQL复制功能的特点
      MySQL复制功能有以下特点:
      主服务器必须启用Bin log(二进制日志),Bin Log里面记录的不是数据,而是SQL语句,就是在主服务器上执行过的操作。
      从服务器本身也可以充当主服务器,进而设置链式复制服务器群组,达到多机数据互相同步的目的。公司业务网点前置上的同步方式就是采用了双机链式主从复制,即双向异步主从复制。
2.MySQL数据复制功能在公司业务系统前置中的应用
2.1公司业务系统网点前置的部署方式
      省内公司业务系统网点前置共有两台服务器,通过负载均衡设备(F5)接收来自网点终端发起的交易。如下图所示,由于F5负载均衡功能的作用,来自终端的交易被均衡分配到两台前置上,流水信息也被分别记录在两台前置上。
2.2 MySQL数据同步功能在公司业务网点前置中的作用
      由于公司业务支持取消、冲正类交易,在运行此类交易时,需要检索原交易的相关信息,因此对信息的完整性和连续性有特定的要求,而MySQL的复制功能,正好完成了数据同步的作用,通过MySQL数据复制,使各台前置上的数据一致,以满足业务系统的要求。
2.3 存在的问题
      在系统上线后的运维工作中,我们发现该双机同步会有失败的情况。数据复制失败后,前置服务器将无法获取其它服务器上的流水信息,如果被冲正或撤销的原交易信息产生在其它服务器上时,前台界面会提示:找不到原流水信息,导致交易失败。
      为了进一步确认问题原因,我们对应用及数据库日志进行分析,发现导致失败的原因是双机ej表中有主键冲突的记录。ej表的数据由四列数据组成,分别是日期,机构号,柜员号,交易流水号,当同一机构的同一柜员,在一天之内分别登录到两台前置的时候,就会在两台前置上产生主键相同的流水信息,这些主键冲突的信息,是导致双机同步失败的原因。
      在公司业务网点前置负载均衡功能上线的文档中,有针对网点登录情况的要求,即省内网点机构通过F5强制分配连接到网点服务器,但是同一机构下的终端只能而且必须同时连接在同一网点前置服务器。该要求的实现,需要同一网点的终端必须在同一网段,并且需要省中心负载均衡设备(F5)针对掩码进行设置,促使同一网段的终端登录到同一台前置上。但在实际应用中,网点网络情况复杂,导致仍会出现同一网点的台席登录到不同前置的情况,进而出现重复流水的问题。最终导致复制过程失败,双机数据内容得不到同步,无法满足数据一致性的要求。
3.针对MySQL数据同步功能的完善讨论
3.1 MySQL自身对同步问题的完善方法
      如何解决双机乃至多机复制中流水冲突的问题呢?在MySQL官方使用手册中,我们可以看到,对于5.0以后的MySQL,可以通过数据库的系统变量auto_increment_increment 和 auto_increment_offset来控制自增序列的步长和起点值,通过对自增序列的步长和起点值的设置,使各台服务器之间的流水不再重复,进而避免流水重复导致的同步失败。
      auto_increment_increment和auto_increment_offset的默认值均为1,此时服务器自增序列(AUTO_INCREMENT)的值为1,2,3...
      通过对auto_increment_increment和auto_increment_offset的值进行设置,可以改变自增序列的值。
      具体的设置方法如下:
      首先查询两个变量的当前值,使用命令:
      mysql> SHOW VARIABLES LIKE 'auto_increment_%';
                | Variable_name            | Value |
               +--------------------------+-------+
               | auto_increment_increment | 1     |
               | auto_increment_offset    | 1     |
               +--------------------------+-------+
               2 rows in set (0.00 sec)
      此时,对服务器1进行如下设置
      mysql> SET @auto_increment_increment=2;
      mysql> SET @auto_increment_offset=1;
      此时,再查询两个变量的值,已经变为:
      mysql> SHOW VARIABLES LIKE 'auto_increment_%';
                | Variable_name            | Value |
               +--------------------------+-------+
               | auto_increment_increment | 2     |
               | auto_increment_offset    | 1     |
               +--------------------------+-------+
               2 rows in set (0.00 sec)
      此时,服务器1自增序列的步长被设置为2,起点值为1,产生自增序列(AUTO_INCREMENT)的值为1,3,5,7,9...
      如果对服务器2进行如下设置
      mysql> SET @auto_increment_increment=2;
      mysql> SET @auto_increment_offset=2;
      此时,再查询两个变量的值,已经变为:
      mysql> SHOW VARIABLES LIKE 'auto_increment_%';
                | Variable_name            | Value |
               +--------------------------+-------+
               | auto_increment_increment | 2     |
               | auto_increment_offset    | 2     |
               +--------------------------+-------+
               2 rows in set (0.00 sec)
      此时,服务器2的自增序列步长值为2,起点值为2,产生的自增序列(AUTO_INCREMENT)的值为2,4,6,8,10...
      可见,通过对auto_increment_increment和auto_increment_offset两个参数进行不同的设置,服务器1和服务器2后续产生的自增序列值将发生变化,并且彼此不重复,如果采用各自的自增序列作为主键,可以避免双机复制时主键冲突的问题。
      但是,通过检查,目前邮政系统中使用的MySQL版本为4.0,不支持上述参数的设置。况且,MySQL自身提供的自增序列默认要求为数值型(int),而流水表中的流水号为字符类型(varchar),如果在原有主键基础上再增加一列自增序列作为联合主键,将改变现有表结构,因此MySQL自身提供的解决方式并不适合公司业务系统中的同步问题。
3.2 针对非自增序列做主键的多机复制方法探析
      在已经部署了网络负载均衡的情况下,在不改变原有业务系统表结构的前提下,解决服务器之间流水重复的问题,可行性办法之一就是通过算法的改进来进行流水的分配。下面,我们尝试仿照自增序列的特点,提出针对现有系统的解决方案,在尽可能小的改动下,解决流水重复的问题。
      为了解决流水分配的问题,我们需要对特定的服务器,指定其流水的起点,并统一各台服务器流水增长的步长。我们引入下述模型对流水进行描述:假设该系统共有N台服务器,服务器编号为i(1<=i<=N),则第i台前置上流水号ej_seq_noi的产生模型为
 
      其中i为服务器编号,N为服务器总数,n为自然数。
      在具体的实施过程中,i是对服务器编号(ServerID),也是该服务器节点的流水起始值,需要作为一个常量写入操作系统的环境变量中。同时需要写入环境变量的,还有流水增加的步长N(也是服务器总数)。
      假设系统服务器共有为3台,则变量N=3,i取值为分别为1,2,3,则各台服务器上预期分配的流水如下表所示:
      可见,当按上述模型建立流水后,可以有效的区分各台服务器的流水号。需要注意的是,当单台服务器增加流水时,是在自身预期流水中增加,而不是在全部流水中增加,因为经过MySQL同步后,各台服务器将拥有所有服务器的全部流水,此时每台服务器上的流水号都是连续的自然数序列。由于流水号产生遵循模型,所以服务器i的预期流水可以看作是自然数序列中模除服务器总数(N)等于i的那部分数值,取出现有这部分集合的最大值,再增加一个步长值,即可得到该服务器新的最大流水号。
      为了进一步测试方法的可行性,我们搭建了两台测试服务器作为测试环境,来验证模型的有效性。搭建过程中使用的操作系统版本为:Red Flag DC Server release 5.0 (Trinity SP1),数据版本与公司业务前置中的版本相同,采用MySQL4.1.12-log。所有同步设置参照公司业务网点前置中的配置,服务器ip分别为10.235.4.51,10.235.4.52,对应的服务器编号(ServID)分别为1,2。并在数据库中,仿照ej表的主键建立如下测试用表ej_test :
      create table ej_test ( ej_work_date varchar(8), ej_seq_no varchar(8), ej_tlr_no varchar(8), ej_inst_no varchar(9), ej_check_flag int(11),primary key (ej_work_date,ej_seq_no,ej_tlr_no,ej_inst_no) ) ENGINE=MyISAM ; 
      建成之后的表结构如下:
+---------------+------------+------+-----+---------+-------+
| Field         | Type       | Null | Key | Default | Extra |
+---------------+------------+------+-----+---------+-------+
| ej_work_date  | varchar(8) |      | PRI |         |       |
| ej_seq_no     | varchar(6) |      | PRI |         |       |
| ej_tlr_no     | varchar(8) |      | PRI |         |       |
| ej_inst_no    | varchar(9) |      | PRI |         |       |
| ej_check_flag | int(11)    | YES  |     | NULL    |       |
+---------------+------------+------+-----+---------+-------+
      建表完成后,需要配置环境变量,在my_cpcb.cnf 中增加对表ej_test的同步设置:
      replicate-do-table=cpcb.ej_test
      配置后重新授权:
      1号机(10.235.4.51):
      $mysql -u root –p
      $mysql> use mysql;
      $mysql> delete from user  where user='replication';
      $mysql>GRANT REPLICATION SLAVE ON *.* TO 'replication'@'10.235.4.52' IDENTIFIED BY 'replication';

      2号机(10.235.4.52):
      $mysql -u root –p
      $mysql> use mysql;
      $mysql> delete from user  where user='replication';
      $mysql>GRANT REPLICATION SLAVE ON *.* TO 'replication'@'10.235.4.51' IDENTIFIED BY 'replication';
      重新授权后,双机已经可以对新增的ej_test 表进行复制。为了按之前的模型产生相应的流水,我们在双机分别编写如下测试脚本:
      #!/bin/bash   

      N=2        /*设置服务器总数 (总共两台服务器,所以N=2)*/
      ServID=1   /*设置当前服务器编号,1号机为1,2号机为2,以此类推*/
      #以静默模式取出当前最大流水序号
      if [ $ServID == $N ]
      then
      MaxSEQ=`mysql -ucpcb -pcpcb --silent  <<EOF
      use cpcb;
      select max(ej_seq_no + 0 ) from ej_test where ej_seq_no%${N}=0;
      quit
      EOF`
      else
      MaxSEQ=`mysql -ucpcb -pcpcb --silent  <<EOF
      use cpcb;
      select max(ej_seq_no + 0 ) from ej_test where ej_seq_no%${N}=$ServID;
      quit
      EOF`
      fi
      #没有记录时,设置最大流水为0
      if [ $MaxSEQ == NULL ]; then
MaxSEQ=0 
      fi
      #设置新流水号
      if [ "$MaxSEQ" -ge "$ServID" ]
      then 
ArgSEQ=`expr $MaxSEQ + $N`
      else
ArgSEQ=$ServID
      fi
      #根据新流水号,插入新记录
      mysql -ucpcb  -pcpcb <<EOF  
use cpcb;
insert into ej_test values ("20130517","$ArgSEQ","12345678","123456789","1");
quit
      EOF  
      将上述脚本保存为TestSeq.sh ,增加可执行权限,分别在两台服务器上执行。每执行一次,将插入一条新的记录。最后检查双机记录,发现单独增加到其中一台服务器上的流水,已经顺利被同步到另外一台服务器上,不再有流水冲突的问题了。
      可见,在前置机使用网络设备负载均衡的情况下,该方案可以确保各台前置生成等量独立的流水,彼此之间不重复,以满足数据复制的需要,该流水生成方式具有如下优点:
1.首先,可以有效避免多机复制过程中流水重复的问题;
2.仅针对流水生成算法进行改动,无需对现有表结构更改,不涉及业务逻辑的改动;
3.由于算法仅与应用程序有关,不依赖与数据库本身的自增序列,可以使用在各个版本的MySQL数据库中,更具普遍适应性。
4.结束语
      随着F5等负载均衡设备在邮政计算机系统中的广泛应用,负载均衡设备与多台前置服务器组成网点前置机集群的应模式日益普遍,前置服务器负载均衡的应用模式实现了多台计算机的同时运行,分担系统压力,但是该集群模式下各台服务器上的数据也具有独立性,无法适应对流水信息有完整性、连续性要求的业务系统。本文以公司业务网点前置的负载均衡方案为背景,通过对系统流水的改善设计,增强了MySQL的数据复制功能的实用效果,最终实现在多机负载均衡模式下,各节点服务器数据的完整性和一致性,达到了交易分散处理,流水信息同步存储的效果。为采用多服务器负载均衡而对数据信息有完整性要求的业务系统,探索了解决途径。
参考文献
1.《MySQL 4.1 Reference Manual》 
2.《MySQL 5.1 Reference Manual》 
网站首页 关于我们免责声明联系我们
版权所有:辽宁省通信学会  备案号:辽ICP备11005629
联系电话:024-22517766  地址:沈阳市沈河区北站路72号


网站建设:恒昊互联网络