复制介绍及搭建,了然manager进度和worker进度的启动顺序

 测试的代码主要效用:开启一个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复制可以实时备份数据;

  • 复制介绍及搭建,了然manager进度和worker进度的启动顺序。其次点是减轻数据库服务器的压力,多台服务器的属性一般比单台要好。但是MySQL复制不吻合大数据量,大数据量推荐应用集群。

MySQL复制进度分成三步:

  • master将改变记录到二进制日志(binary
    log)。这一个记录进程叫做二进制日志事件,binary log events;

  • slave将master的binary log events拷贝到它的接入日志(relay log);

  • slave重做衔接日志中的事件,将改成使用到祥和的数据库中。MySQL复制是异步的且串行化的

www.30064.com 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作为高性能服务器的主演,为众多的营业所和村办服务,他的经过模型相比经典,如下所示:

www.30064.com 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的简化版本。
www.30064.com 3

条件准备

master 192.168.1.5

slave 192.168.1.6

OS:Oracle Linux 6.1

MySQL:5.5.37

www.30064.com 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)分配复制权限

主库和从库均须求实践

www.30064.com 5

2)清空日志文件

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

www.30064.com 6

要求小心的是,假如不想清空日志文件的话,须求记录当前master的log_file和log_pos,并在底下启用复制操作时指定那多少个参数或者在slave的配备文件指定。

Slave设置

1) 修改从服务器server-id

www.30064.com 7

修改完事后须要重启数据库

2)清空日志文件,同Master

3)启用复制

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

www.30064.com 8

master_log_pos的值为0,因为它是日记的始发地方;master_log_file是发端日志文件。假若master日志没有被清空,那里就是眼下master的日记信息

亟需注意的是,默认情状下,会联合该用户下具有的DB,假诺想限定哪些DB,有3种思路

  • 在master上的/etc/my.inf中经过参数binlog-do-db、binlog-ignore-db设置必要联合的数据库

  • 在履行grant分配权限操作的时候,限定数据库

  • 在slave上限制数据库使用replicate-do-db=dbname

4)开启slave

www.30064.com 9

5)确认Slave是或不是和Mater成功通讯。借使Slave_IO_Running和Slave_SQL_Running都是yes,则表明配置成功

www.30064.com 10

测试

Master创设数据库

www.30064.com 11

Slave查看数据库已协同

www.30064.com 12

Master成立表插入数据

www.30064.com 13

Slave查看

www.30064.com 14

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

填补表明

1)做了MySQL主从复制将来,使用mysqldump对数据备份时,一定要注意听从如下格局:

www.30064.com 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参数。同时二进制日志也必须启用。

www.30064.com 16

理所当然,扩充复制的级联层次,同一个改成传到最尾部的Slave所须要通过的MySQL也会越多,同样可能导致延时较长的风险。即使基准允许,倾向于经过拆分成七个Replication集群来缓解。

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

www.30064.com 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步是为了不让过程重新决定终端,因为一个进程控制一个极端的必要条件是会话COO(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

其它,会话、进程组、进程的关联如下图所示,那张图有助于更好的精晓。
www.30064.com 18

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

www.30064.com 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进度也退出。

www.30064.com 20

二、主从服务器工作原理

平整重启命令

平滑停止命令 + 启动命令

再查看进度

MySQL主从复制的系列:

查看进程情形

翻开过程情状这些借鉴了workerman的思路,管理员给master进程发送SIGUSR1信号,告诉主进程,我要看有着进度的新闻,master进度,master进程将自我的长河音讯写入配置好的文本路径A中,然后发送SIGUSR1www.30064.com ,,告诉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检测五遍。

www.30064.com 21

1)基于语句的复制

任何布置

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

除却,也足以支撑多职务,每个职分几个经过独立开,统一由master进度管理。

代码已经停放github中,有趣味的可以试试,不匡助windows哦,有哪些错误还望提议来。

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

2)基于行的复制

参照小说

凭回忆想到的参阅文章,查了好多遗忘了

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

然后实施退出

3)混合类型的复制

www.30064.com 22

做事步骤:

查阅进度确实丢失了

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

 

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

3、从服务器得到主的二进制日志写入中继日志中

4、从服务器开启SQL线程将二进制日志内容执行,已毕数量同步。

试验一、使用三台服务器器,一台主两台从

mysql-master192.168.11.102

MySQL-slave1192.168.11.103

mysql-slave2192.168.11.106

一、首先在主MySQL上安装时间同步工具ntp

1、yum -y install ntp

2、编辑/etc/ntp.conf配置文件

vim/etc/ntp.conf

增进底下两句

server127.127.1.0

fudge127.127.1.0 startum 8

sed -n ‘25,28p’ /etc/ntp.conf查看

3、重启ntp服务

service ntp restart 

4、在两台从MySQL上设置ntpdate工具

yum -y install ntpdate

1、在两台从服务器上输入ntpd +主MySQL的IP地址

ntpdate 192.168.11.102将团结的岁月同步到主MySQL上

2、多刷新四次后意识时间差越来越小

因为日子在上扬的时候会有差错。所以时间共同命令要平常的去实践。所以就要设置一个周期性安插职责来缓解

诸如此类三台服务器的小时哪怕一道的了

二、安装MySQL服务

在主MySQL上配置

1、cp /usr/share/doc/mysql-server-5.1.71/my-medium.cnf

/etc/my.cnf

vim /etc/my.conf

【mysqld】中

添加log-slave-updates=true

修改server-id= 11

2、重启MySQL

假设遇上这一个破绽百出就是讲明您只装了服务端而并未主客户端

3、在主上给从服务器授权

grant replication slave on *.* to

‘mysqlslave’@’192.168.11.%’ identified b y ‘123123’;

flush privileges;

4、查看授权表:mysql> show

master status;

三、编辑从服务器两台配置一样,然则server-id的数字无法一如既往

1、修改配置文件指定从日志索引

[root@localhost ~]# vim /etc/my.conf

添加

relay-log=relay-log-bin

relay-log-index=salve-relay-bin.index

修改server-id= 12

2、重启

/etc/init.d/mysqld restart

3、登陆MySQL授权

mysql -uroot -p123123

change

master to
master_host=’192.168.11.102′,master_user=’myslave’,master_password=’123123′

,master_log_file=’mysql-bin.000003′,master_log_pos=550;

start slave;

show slave status\G;

在主MySQL上创立一个库

查看从服务器,操作是或不是同步。

发表评论

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

网站地图xml地图