zoukankan      html  css  js  c++  java
  • 使用pt-heartbeat检测主从复制延迟

    不要用SECONDS_BEHIND_MASTER来衡量MYSQL主备的延迟时间,原因如下:

    A:备库Seconds_behand_master值是通过将服务器当前的时间戳与二进制日志中的事件的时间戳对比得到的,所以只有在执行事件时才能报告延迟

    B:如果备库复制线程没有运行,就会报延迟为null

    C:一些错误,如主备的max_allowed_packet不匹配或者网络不稳定时,可能中断复制或者停止复制线程,但Seconds_behand_master将显示为0而不是显示错误

    D:即使备库线程正在运行,备库有时候可能无法计算延迟时,如果发生这种情况,备库会报0或者null

    E:一个较大的事务可能导致延迟波动,如:有一个事务更新数据长达一个小时,最后提交,这条更新将比它实际发生时间要晚一个小时才记录到二进制日志中,当备库执行这条语句时,会临时地报告备库延迟一个小时,然后很快又变回0

    F:如果分发主库落后了,并且其本身也有已经追赶上它的备库,备库的延迟将显示为0,而事实上备库和源主库之间此时是有延迟的。

      

    解决这些问题的办法是忽略这个值,并使用一些可以直接观察和衡量的方式来监控备库延迟,最好的解决办法是使用heartbeat record,这是一个在主库上每秒更新一次的时间戳,为了计算延迟,可以直接用备库当前的时间戳减去心跳记录的值,这个方法能够解决刚刚提到的所有问题,另外一个额外的好处是我们还可以通过时间戳知道备库当前的复制状况,包含在percona toolkit里的pt-heartbeat脚本是复制心跳的最流行的一种实现。

      

    心跳还有其他好处,记录在二进制日志中的心跳记录拥有许多用途,如:在一些很难解决的场景下可以用于灾难恢复。

    pt-heartbeat介绍:

    工作原理:

    1,在主上创建一张heartbeat表,按照一定的时间频率更新该表的字段(把时间更新进去)。

    2,从主库连接到从上检查复制的时间记录,和从库的当前系统时间进行比较,得出时间的差异。

     

    使用方法:

    shell > pt-heartbeat [OPTIONS] [DSN] --update|--monitor|--check|--stop

    在主库上创建一个测试库,测试库里创建好heartbeat表,然后开启守护进程来更新xiaoboluo.heartbeat表:

    mysql > create database xiaoboluo;

    mysql > CREATE TABLE heartbeat (

      ts                    varchar(26) NOT NULL,
      server_id             int unsigned NOT NULL PRIMARY KEY,
      file                  varchar(255) DEFAULT NULL,    -- SHOW MASTER STATUS
      position              bigint unsigned DEFAULT NULL, -- SHOW MASTER STATUS
      relay_master_log_file varchar(255) DEFAULT NULL,    -- SHOW SLAVE STATUS
      exec_master_log_pos   bigint unsigned DEFAULT NULL  -- SHOW SLAVE STATUS
    );
     

    shell > pt-heartbeat -D xiaoboluo --update -h localhost --user=username --password=password --daemonize

    在主库上监控从的延迟情况:

    shell > pt-heartbeat -D xiaoboluo --monitor -h slave-server #一直执行,不退出pt-heartbeat -D xiaoboluo --check h=slave-server       #执行一次就退出

     

    常用参数:

    注意:需要指定的参数至少有 --stop,--update,--monitor,--check。其中--update,--monitor和--check是互斥的,--daemonize和--check也是互斥。

    --ask-pass
    隐式输入MySQL密码
    
    --charset
    字符集设置
    
    --check
    检查从的延迟,检查一次就退出,除非指定了--recurse会递归的检查所有的从服务器。
    
    --check-read-only
    如果从服务器开启了只读模式,该工具会跳过任何插入。
    
    --create-table
    在主上创建心跳监控的表,如果该表不存在。可以自己建立,建议存储引擎改成memory。通过更新该表知道主从延迟的差距。
    CREATE TABLE heartbeat (
      ts                    varchar(26) NOT NULL,
      server_id             int unsigned NOT NULL PRIMARY KEY,
      file                  varchar(255) DEFAULT NULL,    -- SHOW MASTER STATUS
      position              bigint unsigned DEFAULT NULL, -- SHOW MASTER STATUS
      relay_master_log_file varchar(255) DEFAULT NULL,    -- SHOW SLAVE STATUS
      exec_master_log_pos   bigint unsigned DEFAULT NULL  -- SHOW SLAVE STATUS
    
    );
    heratbeat表一直在更改ts和position,而ts是我们检查复制延迟的关键。
    
    --daemonize
    执行时,放入到后台执行
    
    --user
    -u,连接数据库的帐号
    
    --database
    -D,连接数据库的名称
    
    --host
    -h,连接的数据库地址
    
    --password
    -p,连接数据库的密码
    
    --port
    -P,连接数据库的端口
    
    --socket
    -S,连接数据库的套接字文件
    
    --file 【--file=output.txt】
    打印--monitor最新的记录到指定的文件,很好的防止满屏幕都是数据的烦恼。
    
    --frames 【--frames=1m,2m,3m】
    在--monitor里输出的[]里的记录段,默认是1m,5m,15m。可以指定1个,如:--frames=1s,多个用逗号隔开。可用单位有秒(s)、分钟(m)、小时(h)、天(d)。
    
    --interval
    检查、更新的间隔时间。默认是见是1s。最小的单位是0.01s,最大精度为小数点后两位,因此0.015将调整至0.02。
    
    --log
    开启daemonized模式的所有日志将会被打印到制定的文件中。
    
    --monitor
    持续监控从的延迟情况。通过--interval指定的间隔时间,打印出从的延迟信息,通过--file则可以把这些信息打印到指定的文件。
    
    --master-server-id
    指定主的server_id,若没有指定则该工具会连到主上查找其server_id。
    
    --print-master-server-id
    在--monitor和--check 模式下,指定该参数则打印出主的server_id。
    
    --recurse
    多级复制的检查深度。模式M-S-S...不是最后的一个从都需要开启log_slave_updates,这样才能检查到。
    
    --recursion-method
    指定复制检查的方式,默认为processlist,hosts。
    
    --update
    更新主上的心跳表。
    
    --replace
    使用--replace代替--update模式更新心跳表里的时间字段,这样的好处是不用管表里是否有行。
    
    --stop
    停止运行该工具(--daemonize),在/tmp/目录下创建一个“pt-heartbeat-sentinel” 文件。后面想重新开启则需要把该临时文件删除,才能开启(--daemonize)。
    
    --table
    指定心跳表名,默认heartbeat。

     

    测试环境:

    Master  192.168.0.68:3306

    Slave   192.168.0.38:3306

      

    1,在主上运行:--daemonize表示守护进程,后台运行。

     [root@xiaoboluo_192.168.0.68 ~]# pt-heartbeat --user=root --ask-pass --host=127.0.0.1 --create-table -D xiaoboluo --interval=1 --update --replace --daemonize

    Enter password: 

    [root@xiaoboluo_192.168.0.68 ~]#

    [root@xiaoboluo_192.168.0.68 ~]# pgrep -fl pt-heartbeat4156perl /usr/bin/pt-heartbeat -D xiaoboluo --table=heartbeat --create-table --update -h 127.0.0.1 -uroot --ask-pass --daemonize

    [root@xiaoboluo_192.168.0.68 ~]#

      

    3.在主上运行监测复制延迟

    [root@xiaoboluo_192.168.0.68 ~]# pt-heartbeat -D xiaoboluo --table=heartbeat --monitor -h 192.168.0.68

    0.00s [  0.00s,  0.00s,  0.00s ]
    0.00s [  0.00s,  0.00s,  0.00s ]
    0.00s [  0.00s,  0.00s,  0.00s ]
    0.00s [  0.00s,  0.00s,  0.00s ]
    0.00s [  0.00s,  0.00s,  0.00s ]

    0表示从没有延迟。 [ 0.00s, 0.00s, 0.00s ] 表示1m,5m,15m的平均值。可以通过--frames去设置。

      

    我们这里看见复制没有延迟,那么我们可以使用压力工具测试一下(这里因为是虚拟机做测试,性能比较差,所以直接使用存储过程循环插入数据做测试了)。在主库创建测试数据库sbtest,随便创建一个测试表:sbtest;

    mysql>create database sbtest;

    Query OK, 1 row affected (0.00 sec)

    mysql>create table sbtest(id int unsigned not null auto_increment primary key,test varchar(20));

     

    创建存储过程:

    mysql > delimiter $$

    mysql > create procedure test_sbtest(in test_times int)
        -> begin
        -> set @x = 0;
        -> ins: loop
        -> set @x = @x + 1;
        -> if @x = test_times then
        -> leave ins;
        -> end if;
        -> insert into sbtest(test) values('test_sbtest');
        -> end loop ins;
        -> end $$
    Query OK, 0 rows affected (0.01 sec)
     
    mysql > delimiter ;
    mysql > call test_sbtest(100000);  #这里调用存储过程循环写入10W次,会有一段时间
    Query OK, 0 rows affected (5 min 22.40 sec)
      

    再次检测复制延时:

    [root@xiaoboluo_192.168.0.68 ~]# pt-heartbeat -D xiaoboluo --table=heartbeat --monitor -h 192.168.0.38

    0.00s [  0.00s,  0.00s,  0.00s ]
    0.00s [  0.00s,  0.00s,  0.00s ]
    0.00s [  0.00s,  0.00s,  0.00s ]
    0.00s [  0.00s,  0.00s,  0.00s ]
    0.00s [  0.00s,  0.00s,  0.00s ]
    0.00s [  0.00s,  0.00s,  0.00s ]
    0.00s [  0.00s,  0.00s,  0.00s ]
    0.00s [  0.00s,  0.00s,  0.00s ]
    0.00s [  0.00s,  0.00s,  0.00s ]
    0.00s [  0.00s,  0.00s,  0.00s ]
    0.00s [  0.00s,  0.00s,  0.00s ]
    5.34s [  0.09s,  0.02s,  0.01s ]
    0.00s [  0.09s,  0.02s,  0.01s ]
    0.00s [  0.09s,  0.02s,  0.01s ]
    0.00s [  0.09s,  0.02s,  0.01s ]
    0.00s [  0.09s,  0.02s,  0.01s ]
    0.00s [  0.09s,  0.02s,  0.01s ]
    0.00s [  0.09s,  0.02s,  0.01s ]
    0.00s [  0.09s,  0.02s,  0.01s ]
    0.00s [  0.09s,  0.02s,  0.01s ]

    1.07s [  0.11s,  0.02s,  0.01s ]

    在上面的输出结果中红色字体部分可以看到延迟输出了

    我们还可以使用--check监测一次就退出:

    [root@xiaoboluo_192.168.0.68 ~]# pt-heartbeat -D xiaoboluo --table=heartbeat --check -h 192.168.0.38

    0.00

    [root@xiaoboluo_192.168.0.68 ~]#

     

    注意:如果想把这个输出结果加入自动化监控,那么可以使用如下命令使监控输出写到文件,然后使用脚本定期过滤文件中的最大值作为预警即可:

    pt-heartbeat -D xiaoboluo --monitor -h 192.168.0.38  --log=/tmp/b.txt  --daemonize  #注意--log选项必须在有--daemonize参数的时候才会打印到文件中,且这个文件的路径最好在/tmp下,否则可能因为权限问题无法创建
     
    #下面是定期过滤--log文件中最大值的脚本,加入监控调用即可:
    #!/bin/bash
    cat /tmp/b.txt > /tmp/b_tmp.txt
    echo > /tmp/b.txt
    max_time=`cat /tmp/b_tmp.txt |grep -v '^$' |awk '{print $1}' |sort -k1nr |head -1`

    echo "$max_time"

      

    2,如何关闭主上面执行的后台进程。可以用参数--stop 去关闭:

    [root@xiaoboluo_192.168.0.68 ~]# pt-heartbeat --stop #注意,这个命令会把所有的pt-heartbeat进程都停掉

    Successfully created file /tmp/pt-heartbeat-sentinel

    [root@xiaoboluo_192.168.0.68 ~]#

    这样就把在主上开启的进程杀掉了,后续要继续开启后台进行的话,需要把/tmp/pt-heartbeat-sentinel 文件删除,否则启动不了

  • 相关阅读:
    面试题
    ajax部分
    jquery部分
    javascript部分
    webpack入门
    jQuery 实现下载进度条
    webSocket入门
    Ajax实现下载进度条
    C# IDisposable接口
    nuget必备插件(待续)
  • 原文地址:https://www.cnblogs.com/DataArt/p/10174638.html
Copyright © 2011-2022 走看看