菜单

MySQL 复制介绍及搭建

2019年2月2日 - 金沙编程资讯

 测试的代码主要意义:开启一个tcp服务器。然后设置了管制过程和劳作历程start的回调举办更名。设置了pid_file保存了服务端启动的mast进度。

一、理论篇

引言

近年支付一个小效能,用到了队列mcq,启动一个历程消费队列数据,前面发现一个进度处理不复苏了,又加了一个进程,过了段时日又处理不回复了……

那种格局每趟都要修改crontab,即使经过挂掉了,不会马上的开行,要等到下次crontab执行的时候才会启动。关闭(重启)进度的时候用的是kill,那也许会丢掉正在处理的数量,比如下边那个事例,我们假诺sleep进程即使处理逻辑,那里为了明确看出效果,将拍卖时间放大到10s:

<?php
$i = 1;
while (1) {
    echo "开始第[{$i}]次循环\n";
    sleep(10);
    echo "结束第[{$i}]次循环\n";
    $i++;
}

当我们运行脚本之后,等到循环起来之后,给进程发送
kill {$pid},默许发送的是数码为15的SIGTERM信号。假设$i是从队列获得的,获得2的时候,正在处理,大家给程序发送了kill信号,和队列数据丢失一样,难点比较大,因而我要想方法解决那几个题材。

开始第[1]次循环
结束第[1]次循环
开始第[2]次循环


[1]    28372 terminated  php t.php

MySQL复制介绍

MySQL复制就是一台MySQL服务器(slave)从另一台MySQL服务器(master)进行日志的复制然后再分析日志并采纳到我,类似Oracle中的Data
Guard。

MySQL复制有那么些好处:

MySQL复制进程分成三步:

图片 1

<?php
//创建Server对象,监听 127.0.0.1:9501端口
$serv = new swoole_server("127.0.0.1", 9501);
$serv->set(array(
    'max_request ' => 10, //reactor thread num
    'worker_num' => 4,    //worker process num
    'log_file' => 'swoole.log',
    'pid_file' => 'server.pid',
));



$serv->on('managerStart',function($serv){
    swoole_set_process_name("managerprocess");
});

$serv->on('workerStart',function($serv, $worker_id){
    if($worker_id >= $serv->setting['worker_num']) {
        swoole_set_process_name("workprocess_".($worker_id-$serv->setting['worker_num']));
    } else {
        swoole_set_process_name("workprocess_{$worker_id}");
    }
});
$serv->on('start',function($serv){
    echo "到这一步说明服务已经起来了,manager,work都已经回调start完成";
});
//监听连接进入事件
$serv->on('connect', function ($serv, $fd) {  
    echo "Client: Connect.\n";
});

//监听数据接收事件
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
    $serv->send($fd, "Server: ".$data);
});

//监听连接关闭事件
$serv->on('close', function ($serv, $fd) {
    echo "Client: Close.\n";
});

//启动服务器
$serv->start(); 

1、集团中单台MySQL难题

nginx进度模型

此时我想到了nginx,nginx作为高质量服务器的栋梁之材,为众多的营业所和村办服务,他的经过模型比较经典,如下所示:

图片 2

领队通过master进度和nginx举行互动,从/path/to/nginx.pid读取nginx
master进度的pid,发送信号给master进度,master根据不相同的信号做出不一致的处理,然后上报音信给管理员。worker是master进度fork出来的,master负责管理worker,不会去处理业务,worker才是现实事务的处理者,master可以操纵worker的淡出、启动,当worker意外退出,master会收到子进度退出的音讯,也会再一次起动新的worker进度补充上来,不让业务处理受影响。nginx还是可以平滑退出,不丢掉任何一个正值处理的数量,更新配备时nginx能够完毕不影响线上服务来加载新的布署,那在请求量很大的时候特意有用。

MySQL复制搭建

敞开服务器后

1)单点故障

进度设计

看了nginx的进模型,我们完全可以支付一个近乎的类库来满足处理mcq数据的要求,做到单文件控制所有进度、可以平滑退出、可以查看子进度情况。不要求太复杂,因为我们处理队列数据接受一定的推移,做到nginx那样不间断服务比较麻烦,费时费劲,意义不是很大。设计的进程模型跟nginx类似,更像是nginx的简化版本。
图片 3

条件准备

master 192.168.1.5

slave 192.168.1.6

OS:Oracle Linux 6.1

MySQL:5.5.37

图片 4

2)服务不可用不能够处理多量的高并发数据请求

进度信号量设计

信号量是经过间通信的一种方法,比较简单,单功效也相比弱,只好发送信号给进度,进程依据信号做出不一样的拍卖。

master进度启动的时候保存pid到文件/path/to/daeminze.pid,管理员通过信号和master进程通信,master进度安装3种信号,遇到差距的信号,做出区其他拍卖,如下所示:

SIGINT  => 平滑退出,处理完正在处理的数据再退出
SIGTERM => 暴力退出,无论进程是否正在处理数据直接退出
SIGUSR1 => 查看进程状态,查看进程占用内存,运行时间等信息

master进度通过信号和worker进程通信,worker进度安装了2个信号,如下所示:

SIGINT  => 平滑退出
SIGUSR1 => 查看worker进程自身状态

为何worker进度只设置2个信号吧,少了个SIGTERM,因为master进度收到信号SIGTERM随后,向worker进程发送SIGKILL信号,默许强制关闭进度即可。

worker进度是经过master进度fork出来的,那样master进程可以透过pcntl_wait来等待子进程退出事件,当有子进度退出的时候重临子进度pid,做拍卖并启动新的经过补充上来。

master进度也通过pcntl_wait来等待接受信号,当有信号到达的时候,会回到-1,那几个地方还有些坑,在下文中会详细讲。

PHP中有2种信号触发的艺术,第一种方法是declare(ticks = 1);,那种频率不高,Zend每执行一遍低级语句,都会去检查进度中是还是不是有未处理的信号,现在早已很少使用了,PHP 5.3.0及前边的本子可能会用到这些。

其次种是经过pcntl_signal_dispatch来调用未处理的信号,PHP 5.4.0及事后的本子适用,可以巧妙的将该函数放在循环中,品质上着力没什么损失,现在推荐适用。

Master配置

1)分配复制权限

主库和从库均需要履行

图片 5

2)清空日志文件

主从库都是默许开启二进制日志文件

图片 6

亟需注意的是,尽管不想清空日志文件的话,要求记录当前master的log_file和log_pos,并在上面启用复制操作时指定那八个参数或者在slave的布署文件指定。

Slave设置

1) 修改从服务器server-id

图片 7

修改完将来须要重启数据库

2)清空日志文件,同Master

3)启用复制

让slave连接master并起首重做master二进制日志中的事件

图片 8

master_log_pos的值为0,因为它是日记的先河地点;master_log_file是发端日志文件。假如master日志没有被清空,那里就是眼前master的日记新闻

内需注意的是,默许情状下,会共同该用户下所有的DB,若是想限定哪些DB,有3种思路

4)开启slave

图片 9

5)确认Slave是不是和Mater成功通讯。假诺Slave_IO_Running和Slave_SQL_Running都是yes,则证实配置成功

图片 10

测试

Master创设数据库

图片 11

Slave查看数据库已同步

图片 12

Master创制表插入数据

图片 13

Slave查看

图片 14

通过以上验证,可以见到主服务器上的改动可以健康同步到从服务器。

补偿表明

1)做了MySQL主从复制未来,使用mysqldump对数据备份时,一定要小心遵守如下情势:

图片 15

诸如此类就足以保留file和position的音讯,在新搭建一个slave的时候,还原完数据库,file和position的音讯也随之更新,接着再start
slave 就可以很便捷的姣好增量同步。

翻看进程,在server->start 后,拉起workNum+2(master,manager进程)。

3)数据丢是未曾主意恢复生机

PHP安装修信号量

PHP通过pcntl_signal安装信号,函数申明如下所示:

bool pcntl_signal ( int $signo , [callback $handler [, bool $restart_syscalls = true ] )

其三个参数restart_syscalls不太好精晓,找了无数资料,也没太查明白,经过考试发现,这些参数对pcntl_wait函数接收信号有影响,当设置为缺省值true的时候,发送信号,进度用pcntl_wait收不到,必须安装为false才足以,看看上面那些事例:

<?php
$i = 0;
while ($i<5) {
    $pid = pcntl_fork();
    $random = rand(10, 50);
    if ($pid == 0) {
        sleep($random);
        exit();
    }
    echo "child {$pid} sleep {$random}\n";
    $i++;
}

pcntl_signal(SIGINT,  function($signo) {
     echo "Ctrl + C\n";
});

while (1) {
    $pid = pcntl_wait($status);
    var_dump($pid);
    pcntl_signal_dispatch();
}

运行之后,我们对父进度发送kill -SIGINT {$pid}信号,发现pcntl_wait没有影响,等到有子进程退出的时候,发送过的SIGINT会一个个实施,比如上边结果:

child 29643 sleep 48
child 29644 sleep 24
child 29645 sleep 37
child 29646 sleep 20
child 29647 sleep 31
int(29643)
Ctrl + C
Ctrl + C
Ctrl + C
Ctrl + C
int(29646)

那是运行脚本之后立即给父进程发送了四遍SIGINT信号,等到一个子历程推出的时候,所有信号都会接触。

但当把安装信号的第多少个参数设置为false

pcntl_signal(SIGINT,  function($signo) {
     echo "Ctrl + C\n";
}, false);

那时候给父进度发送SIGINT信号,pcntl_wait会及时再次来到-1,信号对应的轩然大波也会触发。

所以第多个参数大约意思就是,是不是再次登记此信号,即使为false只登记一回,触发之后就赶回,pcntl_wait就能吸纳音信,如果为true,会重新登记,不会回来,pcntl_wait收不到新闻。

任何复制格局

主主复制

master-slave只好举办单向操作,像互连网中的半双工。master-master能够兑现服务器之间互相同步,且主主复制能够幸免出现单点故障后所有系统宕机。主主复制最大的标题就是数额插入或更新争论。配置方式同主从复制,反过来让slave同步master。注意master_log_file和master_log_pos参数要与master上相应。具体可以参见那里

单一master和多slave

由一个master和七个slave组成的复制系统比较不难。slave之间并不相互通讯,只好与master通讯。如若写操作较少,读操作很多,可以使用。可以将读操作分布到其余slave,从而减轻master的压力。但slave扩大到一定数量时,slave对master的载荷以及互联网带宽都会化为难题。

基本多级复制

读操作很多足以利用单一maste和多slave,但附加到一定slave后连到master的slaveIO线程太多会导致master压力增大,从而造成数据复制延时。多级复制就是为着化解那一个标题。若是想已毕主-从(主)-从多元复制,要求安装log-slave-updates参数。同时二进制日志也务必启用。

图片 16

自然,伸张复制的级联层次,同一个改变传到最尾部的Slave所急需经过的MySQL也会更加多,同样可能造成延时较长的高风险。假设条件允许,倾向于通过拆分成七个Replication集群来缓解。

版权申明:来源:bestvivi,链接:

图片 17

4)数据丢失导致前者不能正常干活

信号量和系统调用

信号量会卡住系统调用,让系统调用即刻回到,比如sleep,当进程正在sleep的时候,收到信号,sleep会即刻重临剩余sleep秒数,比如:

<?php
pcntl_signal(SIGINT,  function($signo) {
     echo "Ctrl + C\n";
}, false);

while (true) {
    pcntl_signal_dispatch();
    echo "123\n";
    $limit = sleep(2);
    echo "limit sleep [{$limit}] s\n";
}

运作之后,按Ctrl + C,结果如下所示:

123
^Climit sleep [1] s
Ctrl + C
123
limit sleep [0] s
123
^Climit sleep [1] s
Ctrl + C
123
^Climit sleep [2] s

下一场查看pid_file里的master进度id是或不是是1827,上图所示。结果肯定是千篇一律的

解决办法

daemon(守护)进程

那种经过一般设计为daemon进程,不受终端控制,不与极端交互,长日子运作在后台,而对此一个进度,大家可以透过上边多少个步骤把她升任为一个正经的daemon进度:

protected function daemonize()
{
    $pid = pcntl_fork();
    if (-1 == $pid) {
        throw new Exception("fork进程失败");
    } elseif ($pid != 0) {
        exit(0);
    }
    if (-1 == posix_setsid()) {
        throw new Exception("新建立session会话失败");
    }

    $pid = pcntl_fork();
    if (-1 == $pid) {
        throw new Exception("fork进程失败");
    } else if($pid != 0) {
        exit(0);
    }

    umask(0);
    chdir("/");
}

拢共分五步:

  1. fork子进度,父进程退出。
  2. 设置子进程为会话老董,进度总监。
  3. 双重fork,父进程退出,子进度继续运行。
  4. 卷土重来文件掩码为0
  5. 切换当前目录到根目录/

第2步是为第1步做准备,设置进度为会话老板,须要条件是经过非经过首席营业官,由此做首回fork,进度主任(父进度)退出,子进度经过posix_setsid()安装为会话首席执行官,同时也为经过高管。

第3步是为着不让进度重新决定终端,因为一个历程控制一个终极的需要条件是会话高管(pid=sid)。

第4步是为着苏醒默许的文本掩码,防止从前做的操作对文本掩码做了设置,带来不要求的麻烦。关于文件掩码,
linux中,文件掩码在成立文件、文件夹的时候会用到,文件的默许权限为666,文件夹为777,创制文件(夹)的时候会用默许值减去掩码的值作为创造文件(夹)的最后值,比如掩码022下创办文件666 - 222 = 644,创造文件夹777 - 022 = 755

掩码 新建文件权限 新建文件夹权限
umask(0) 666 (-rw-rw-rw-) 777 (drwxrwxrwx)
umask(022) 644 (-rw-r–r–) 755 (drwxr-xr-x)

第5步是切换了当前目录到根目录/,网上说防止开始运行他的目录无法被科学卸载,那一个不是太精晓。

对应5步,每一步的各类id变化新闻:

操作后 pid ppid pgid sid
开始 17723 31381 17723 31381
第一次fork 17723 1 17723 31381
posix_setsid() 17740 1 17740 17740
第二次fork 17840 1 17740 17740

除此以外,会话、进程组、进度的关系如下图所示,这张图有助于更好的知情。
图片 18

迄今,你也得以轻松地造出一个daemon进度了。

图片 19

1、扩张MySQL数据库服务器,对数据开展备份,形成主备

命令设计

自家准备给那几个类库设计6个指令,如下所示:

  1. start 启动命令
  2. restart 强制重启
  3. stop 平滑为止
  4. reload 平滑重启
  5. quit 强制甘休
  6. status 查看进度情状

 

2、确保准备的MySQL数据库服务器是一致的

启动命令

起步命令就是默许的流程,依据默许流程走就是开行命令,启动命令会检测pid文件中是不是曾经有pid,pid对应的长河是或不是正规,是还是不是须要再行启航。

下边写一个脚本去重启和为止服务端。(原理就是给mast进度发送信号)

3、主服务器宕机,备份服务器继续工作,数据有担保

强制为止命令

管理员通过输入文件结合pid给master进程发送SIGTERM信号,master进度给所有子进度发送SIGKILL信号,等待所有worker进度退出后,master进度也退出。

<?php
    $options  = 's';
    $command = getopt($options);
    $pidFile = 'server.pid';
    if(isset($command['s'])){
        if($command['s']=='stop'){
            stop();
        }else{
            reload();
        }
    }else{
        die("请输入-s stop|reload");
    }

    function stop(){
        global $pidFile;
        if (file_exists($pidFile)) {
            $pid = file_get_contents($pidFile);

            if (!swoole_process::kill($pid, 0)) {
                echo "PID :{$pid} not exist \n";
                return false;
            }
            swoole_process::kill($pid);
            //等待5秒
            $time = time();
            $flag = false;
            while (true) {
                usleep(1000);
                if (!swoole_process::kill($pid, 0)) {
                    echo "server stop at " . date("y-m-d h:i:s") . "\n";
                    if (is_file($pidFile)) {
                        unlink($pidFile);
                    }
                    $flag = true;
                    break;
                } else {
                    if (time() - $time > 5) {
                        echo "stop server fail.try again \n";
                        break;
                    }
                }
            }
            return $flag;
        } else {
            echo "pid 文件不存在,请执行查找主进程pid,kill!\n";
            return false;
        }
    }

    function reload(){
        global $pidFile;
        if (file_exists($pidFile)) {
            $sig = SIGUSR1;
            $pid = file_get_contents($pidFile);
            if (!swoole_process::kill($pid, 0)) {
                echo "pid :{$pid} not exist \n";
                return;
            }
            swoole_process::kill($pid, $sig);
            echo "send server reload command at " . date("y-m-d h:i:s") . "\n";
        } else {
            echo "pid 文件不存在,请执行查找主进程pid,kill!\n";
        }
    }

MySQL主从复制与读写分离是仔细相关的

强制重启命令

强制停止命令 + 启动命令

先实施重启

读写分离是按照主从复制来完结的

平整停止命令

平整停止命令,管理员给master进度发送SIGINT信号,master进程给所有子进程发送SIGINT,worker进度将我情况标记为stoping,当worker进度下次循环的时候会依照stoping操纵终止,不在接收新的多少,等具备worker过程退出之后,master进程也脱离。

图片 20

二、主从服务器工作规律

平整重启命令

平滑停止命令 + 启动命令

再查看进度

MySQL主从复制的项目:

查阅进程情形

翻开进程意况那些借鉴了workerman的思绪,管理员给master进度发送SIGUSR1信号,告诉主进度,我要看有着进程的新闻,master进程,master进度将自身的进度音信写入配置好的文本路径A中,然后发送SIGUSR1,告诉worker进度把自己的音讯也写入文件A中,由于那一个进程是异步的,不知晓worker进度哪一天写完,所以master进度在此间等待,等具备worker进度都写入文件之后,格式化所有的音信输出,最终输出的情节如下所示:

➜/dir /usr/local/bin/php DaemonMcn.php status
Daemon [DaemonMcn] 信息:
-------------------------------- master进程状态 --------------------------------
pid       占用内存       处理次数       开始时间                 运行时间
16343     0.75M          --             2018-05-15 09:42:45      0 天 0 时 3 分
12 slaver
-------------------------------- slaver进程状态 --------------------------------
任务task-mcq:
16345     0.75M          236            2018-05-15 09:42:45      0 天 0 时 3 分
16346     0.75M          236            2018-05-15 09:42:45      0 天 0 时 3 分
--------------------------------------------------------------------------------
任务test-mcq:
16348     0.75M          49             2018-05-15 09:42:45      0 天 0 时 3 分
16350     0.75M          49             2018-05-15 09:42:45      0 天 0 时 3 分
16358     0.75M          49             2018-05-15 09:42:45      0 天 0 时 3 分
16449     0.75M          1              2018-05-15 09:46:40      0 天 0 时 0 分
--------------------------------------------------------------------------------

等候worker进程将经过新闻写入文件的时候,这几个地点用了个相比较trick的方式,每个worker进度输出一行消息,计算文件的行数,达到worker进程的行数之后表示拥有worker进度都将新闻写入完成,否则,每个1s检测一遍。

图片 21

1)基于语句的复制

其余安顿

别的还加了多个相比实用的成效,一个是worker进度运行时刻范围,一个是worker进度循环处理次数限制,防止长日子循环进程出现内存溢出等意外情形。时间默许是1小时,运行次数默许是10w次。

除外,也能够协理多任务,每个任务多少个过程独立开,统一由master进度管理。

代码已经停放github中,有趣味的可以尝试,不协助windows哦,有何样错误还望提出来。

主进度如故1827,可是工作进程就被reload的了。

2)基于行的复制

参照文章

凭记念想到的参照小说,查了重重记不清了

  1. Linux多义务编程(七)—Linux守护进度及其基础实验
  2. workerman源码

然后实施退出

3)混合类型的复制

图片 22

工作步骤:

翻看进度确实丢失了

1、MySQL从服务器开启I/O线程,项主服务器请求数据同步(获取主服务器上的二进制日志)

 

2、MySQL主服务器开启I/O线程回应从服务器

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图