精华内容
下载资源
问答
  • 2022-02-19 11:18:45

    从MySQL 5.6.5开始新增了一种基于GTID的复制方式。通过GTID保证了每个在主库上提交的事务在集群中有一个唯一的ID。这种方式强化了数据库的主备一致性,故障恢复以及容错能力。

    GTID是什么

    GTID (Global Transaction ID) 是对于一个已提交事务的编号,并且是一个全局唯一的编号。 GTID实际上是由UUID+TID 组成的。其中UUID是一个 MySQL实例的唯一标识。TID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增。

    下面是一个GTID的具体形式:3E11FA47-71CA-11E1-9E33-C80AA9429562:23,冒号分割前边为uuid,后边为TID。

    GTID集合可以包含来自多个MySQL实例的事务,它们之间用逗号分隔。

    如果来自同一MySQL实例的事务序号有多个范围区间,各组范围之间用冒号分隔。例如:e6954592-8dba-11e6-af0e-fa163e1cf111:1-5:11-18,e6954592-8dba-11e6-af0e-fa163e1cf3f2:1-27。

    GTID改进有哪些

    在原来基于二进制日志的复制中,从库需要告知主库要从哪个偏移量进行增量同步,如果指定错误会造成数据的遗漏,从而造成数据的不一致。借助GTID,在发生主备切换的情况下,MySQL的其它从库可以自动在新主库上找到正确的复制位置,这大大简化了复杂复制拓扑下集群的维护,也减少了人为设置复制位置发生误操作的风险。另外,基于GTID的复制可以忽略已经执行过的事务,减少了数据发生不一致的风险。

    主库基于gtid set可以准确的知道从库缺少哪些数据,不会多给从库数据,也不会少给,避免网络带宽浪费。

    mysql主从结构在一主一从情况下对于GTID来说就没有优势了,而对于2台主以上的结构优势异常明显,可以在数据不丢失的情况下切换新主。

    注意:在构建主从复制之前,在一台将成为主的实例上进行一些操作(如数据清理等),通过GTID复制,这些在主从成立之前的操作也会被复制到从服务器上,引起复制失败。也就是说通过GTID复制都是从最先开始的事务日志开始,即使这些操作在复制之前执行。比如在server1上执行一些drop、delete的清理操作,接着在server2上执行change的操作,会使得server2也进行server1的清理操作。

    GTID的工作原理

    1. 当一个事务在主库端执行并提交时,产生GTID,一同记录到binlog日志中。
    2. binlog传输到slave,并存储到slave的relaylog后,读取这个GTID的这个值设置gtid_next变量,即告诉Slave,下一个要执行的GTID值。
    3. sql线程从relay log中获取GTID,然后对比slave端的binlog是否有该GTID。
    4. 如果有记录,说明该GTID的事务已经执行,slave会忽略。
    5. 如果没有记录,slave就会执行该GTID事务,并记录该GTID到自身的binlog,在读取执行事务前会先检查其他session持有该GTID,确保不被重复执行。

    一主一从GTID复制的搭建

    主机规划:

    • master:docker,端口3312
    • slave:docker,端口3313

    master的配置

    配置文件my.cnf内容如下:

    $ cat /home/mysql/docker-data/3313/conf/my.cnf
    # For advice on how to change settings please see
    # http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
    
    [mysqld]
    #
    # Remove leading # and set to the amount of RAM for the most important data
    # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
    # innodb_buffer_pool_size = 128M
    #
    # Remove leading # to turn on a very important data integrity option: logging
    # changes to the binary log between backups.
    # log_bin
    #
    # Remove leading # to set options mainly useful for reporting servers.
    # The server defaults are faster for transactions and fast SELECTs.
    # Adjust sizes as needed, experiment to find the optimal values.
    # join_buffer_size = 128M
    # sort_buffer_size = 2M
    # read_rnd_buffer_size = 2M
    #datadir=/home/mysql/docker-data/3307/data
    #socket=/home/mysql/docker-data/3307/mysql.sock
    
    character_set_server=utf8
    init_connect='SET NAMES utf8'
    
    # Disabling symbolic-links is recommended to prevent assorted security risks
    symbolic-links=0
    
    #log-error=/home/mysql/docker-data/3307/logs/mysqld.log
    #pid-file=/home/mysql/docker-data/3307/mysqld.pid
    lower_case_table_names=1
    server-id=1403311
    log-bin=mysql-bin
    binlog-format=ROW
    auto_increment_increment=1
    auto_increment_offset=1
    # 开启gtid
    gtid_mode=ON
    enforce-gtid-consistency=true
    
    #rpl_semi_sync_master_enabled=1
    #rpl_semi_sync_master_timeout=10000
    

    创建docker实例:

    $ docker run --name mysql3312 -p 3312:3306 --privileged=true -ti -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=order -e MYSQL_USER=user -e MYSQL_PASSWORD=pass -v /home/mysql/docker-data/3312/conf:/etc/mysql/conf.d -v /home/mysql/docker-data/3312/data/:/var/lib/mysql -v /home/mysql/docker-data/3312/logs/:/var/log/mysql -d mysql:5.7
    

    添加用于复制的用户并授权:

    mysql> GRANT REPLICATION SLAVE,FILE,REPLICATION CLIENT ON *.* TO 'repluser'@'%' IDENTIFIED BY '123456';
    Query OK, 0 rows affected, 1 warning (0.01 sec)
    
    mysql> FLUSH PRIVILEGES;
    Query OK, 0 rows affected (0.01 sec)
    

    slave的配置

    配置文件my.cnf内容与master一致,注意修改server-id,保持唯一。

    创建docker实例:

    $ docker run --name mysql3313 -p 3313:3306 --privileged=true -ti -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=order -e MYSQL_USER=user -e MYSQL_PASSWORD=pass -v /home/mysql/docker-data/3313/conf:/etc/mysql/conf.d -v /home/mysql/docker-data/3313/data/:/var/lib/mysql -v /home/mysql/docker-data/3313/logs/:/var/log/mysql -d mysql:5.7
    

    开启GTID同步:

    mysql> change master to master_host='172.23.252.98',master_port=3310,master_user='repluser',master_password='123456',master_auto_position=1;
    Query OK, 0 rows affected, 2 warnings (0.02 sec)
    
    mysql> start slave;
    Query OK, 0 rows affected (0.02 sec)
    

    查看状态:

    mysql> show master status;
    +------------------+----------+--------------+------------------+----------------------------------------+
    | File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                      |
    +------------------+----------+--------------+------------------+----------------------------------------+
    | mysql-bin.000008 |      154 |              |                  | cd2eaa0a-7a59-11ec-b3b4-0242ac110002:1 |
    +------------------+----------+--------------+------------------+----------------------------------------+
    1 row in set (0.00 sec)
    
    mysql> show slave status\G;
    *************************** 1. row ***************************
                   Slave_IO_State: Waiting for master to send event
                      Master_Host: 172.23.252.98
                      Master_User: repluser
                      Master_Port: 3312
                    Connect_Retry: 60
                  Master_Log_File: mysql-bin.000006
              Read_Master_Log_Pos: 419
                   Relay_Log_File: 5dfbef024732-relay-bin.000003
                    Relay_Log_Pos: 632
            Relay_Master_Log_File: mysql-bin.000006
                 Slave_IO_Running: Yes
                Slave_SQL_Running: Yes
                  Replicate_Do_DB:
              Replicate_Ignore_DB:
               Replicate_Do_Table:
           Replicate_Ignore_Table:
          Replicate_Wild_Do_Table:
      Replicate_Wild_Ignore_Table:
                       Last_Errno: 0
                       Last_Error:
                     Skip_Counter: 0
              Exec_Master_Log_Pos: 419
                  Relay_Log_Space: 846
                  Until_Condition: None
                   Until_Log_File:
                    Until_Log_Pos: 0
               Master_SSL_Allowed: No
               Master_SSL_CA_File:
               Master_SSL_CA_Path:
                  Master_SSL_Cert:
                Master_SSL_Cipher:
                   Master_SSL_Key:
            Seconds_Behind_Master: 0
    Master_SSL_Verify_Server_Cert: No
                    Last_IO_Errno: 0
                    Last_IO_Error:
                   Last_SQL_Errno: 0
                   Last_SQL_Error:
      Replicate_Ignore_Server_Ids:
                 Master_Server_Id: 1403311
                      Master_UUID: cd2eaa0a-7a59-11ec-b3b4-0242ac110002
                 Master_Info_File: /var/lib/mysql/master.info
                        SQL_Delay: 0
              SQL_Remaining_Delay: NULL
          Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
               Master_Retry_Count: 86400
                      Master_Bind:
          Last_IO_Error_Timestamp:
         Last_SQL_Error_Timestamp:
                   Master_SSL_Crl:
               Master_SSL_Crlpath:
               Retrieved_Gtid_Set: cd2eaa0a-7a59-11ec-b3b4-0242ac110002:1
                Executed_Gtid_Set: cd2eaa0a-7a59-11ec-b3b4-0242ac110002:1
                    Auto_Position: 1
             Replicate_Rewrite_DB:
                     Channel_Name:
               Master_TLS_Version:
    1 row in set (0.00 sec)
    

    在master.order表插入数据:

    mysql> insert into t_order values(4,"V");
    

    发现数据已经同步至slave:

    mysql> select * from order.t_order;
    +------+------+
    | id   | name |
    +------+------+
    |    4 | V    |
    +------+------+
    3 rows in set (0.00 sec)
    

    先停止slave,再在master.order表插入数据:

    mysql> insert into t_order values(5,"X");
    

    然后再启动slave,发现数据已自动同步:

    mysql> stop slave;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> select * from order.t_order;
    +------+------+
    | id   | name |
    +------+------+
    |    4 | V    |
    +------+------+
    3 rows in set (0.00 sec)
    
    mysql> start slave;
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> select * from order.t_order;
    +------+------+
    | id   | name |
    +------+------+
    |    4 | V    |
    |    5 | X    |
    +------+------+
    4 rows in set (0.00 sec)
    

    遇到的问题

    在slave服务器show slave status:

    Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.
    

    首先检查master和slave的server_id是否一致,如果一致去修改my.cnf文件中的server_id字段:

    mysql> show variables like 'server_id';
    

    然后排查master和slave的uuid是否一致:

    mysql> show variables like '%uuid%';
    

    如果uuid一致去修改data目录下的auto.cnf文件,拷贝整个data目录,把auto.cnf文件也拷贝过来了,里面记录了数据库的uuid,每个库的uuid应该是不一样的。

    更多相关内容
  • 【MySQL】MySQL复制架构

    万次阅读 2022-02-19 11:20:17
    一主多从复制架构 在实际应用场景中,MySQL复制90%以上都是一个Master复制到一个或者多个Slave的架构模式。 在主库读取请求压力非常大的场景下,可以通过配置一主多从复制架构实现读写分离,把大量的对实时性要求...

    一主多从复制架构

    在实际应用场景中,MySQL复制90%以上都是一个Master复制到一个或者多个Slave的架构模式。

    在主库读取请求压力非常大的场景下,可以通过配置一主多从复制架构实现读写分离,把大量的对实时性要求不是特别高的读请求通过负载均衡分部到多个从库上(对于实时性要求很高的读请求可以让从主库去读),降低主库的读取压力,如下图所示。

    image-20220209184742760

    缺点:

    • master不能停机,停机就不能接收写请求
    • slave过多会出现延迟

    由于master需要进行常规维护停机了,那么必须要把一个slave提成master,选哪一个是一个问题?

    某一个slave提成master了,就存在当前master和之前的master数据不一致的情况,并且之前master并没有保存当前master节点的binlog文件和pos位置。

    多主复制架构

    多主复制架构解决了一主多从复制架构中master的单点故障问题。

    image-20220209184852022

    可以配合一个第三方的工具,比如keepalived轻松做到IP的漂移,这样master停机维护也不会影响写操作。

    级联复制架构

    一主多从中如果slave过多,会导致主库的I/O压力和网络压力会随着从库的增加而增长,因为每个从库都会在主库上有一个独立的BINLOG Dump线程来发送事件,而级联复制架构解决了一主多从场景下的,主库额外的I/O和网络压力。

    如下图所示。

    image-20220209184936703

    对比一主多从的架构,级联复制仅仅是从主库Master复制到少量的从库,其他从库再从这少量的从库中复制数据,这样就减轻了主库Master的压力。

    当然也有缺点:MySQL的传统复制是异步的,级联复制场景下主库的数据是经历两次复制才到达其他从库中,期间的延迟要比一主多从复制场景下只经历一次复制的还大。

    可以通过在二级slave上选择表引擎为BLACKHOLE来降低级联复制的延迟。顾名思义,BLACKHOLE引擎是一个“黑洞”引擎,写入BLACKHOLE表的数据并不会写会到磁盘上,BLACKHOLE表永远都是空表,INSERT、UPDATE、DELETE操作仅仅在BINLOG中记录事件。

    下面演示下BLACKHOLE引擎:

    mysql> CREATE TABLE `user` (
        -> `id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
        -> `name` varchar(255) NOT NULL DEFAULT '',
        -> `age` tinyint unsigned NOT NULL DEFAULT 0
        -> )ENGINE=BLACKHOLE charset=utf8mb4;
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> INSERT INTO `user` (`name`,`age`) values("itbsl", "26");
    Query OK, 1 row affected (0.00 sec)
    
    mysql> select * from user;
    Empty set (0.00 sec)
    

    可以看到,存储引擎为BLACKHOLE的user表里没有数据。

    多主与级联复制结合架构

    结合多主与级联复制架构,这样解决了单点master的问题,解决了slave级联延迟的问题。

    image-20220209185030818

    多主复制架构的搭建

    主机规划:

    • master1:docker,端口3314
    • master2:docker,端口3315

    master1的配置

    配置文件my.cnf:

    $ cat /home/mysql/docker-data/3315/conf/my.cnf
    [mysqld]
    character_set_server=utf8
    init_connect='SET NAMES utf8'
    
    symbolic-links=0
    
    lower_case_table_names=1
    server-id=1403314
    log-bin=mysql-bin
    binlog-format=ROW
    auto_increment_increment=2 # 几个主库,这里就配几
    auto_increment_offset=1 # 每个主库的偏移量需要不一致
    gtid_mode=ON
    enforce-gtid-consistency=true
    binlog-do-db=order      # 要同步的数据库
    

    启动docker:

    $ docker run --name mysql3314 -p 3314:3306 --privileged=true -ti -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=order -e MYSQL_USER=user -e MYSQL_PASSWORD=pass -v /home/mysql/docker-data/3314/conf:/etc/mysql/conf.d -v /home/mysql/docker-data/3314/data/:/var/lib/mysql -v /home/mysql/docker-data/3314/logs/:/var/log/mysql -d mysql:5.7
    

    添加用于复制的用户并授权:

    mysql> GRANT REPLICATION SLAVE,FILE,REPLICATION CLIENT ON *.* TO 'repluser'@'%' IDENTIFIED BY '123456';
    Query OK, 0 rows affected, 1 warning (0.01 sec)
    
    mysql> FLUSH PRIVILEGES;
    Query OK, 0 rows affected (0.01 sec)
    

    开启同步master1(这里的user来自master2):

    mysql> change master to master_host='172.23.252.98',master_port=3315,master_user='repluser',master_password='123456',master_auto_position=1;
    Query OK, 0 rows affected, 2 warnings (0.03 sec)
    
    mysql> start slave;
    Query OK, 0 rows affected (0.00 sec)
    

    master2的配置

    master2的配置与master1类似。

    主要区别在于my.cnf中有一个属性需要不一致:

    auto_increment_offset=2 # 每个主库的偏移量需要不一致
    

    测试:

    在master2创建表,并添加数据:

    mysql> create table t_order(id int primary key auto_increment, name varchar(20));
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> insert into t_order(name) values("A");
    Query OK, 1 row affected (0.01 sec)
    
    mysql> insert into t_order(name) values("B");
    Query OK, 1 row affected (0.00 sec)
    
    mysql> select * from t_order;
    +----+------+
    | id | name |
    +----+------+
    |  2 | A    |
    |  4 | B    |
    +----+------+
    2 rows in set (0.00 sec)
    

    可以发现master2中id的步长为2,且从2开始自增。

    然后在master1查询数据,并添加:

    mysql> select * from t_order;
    +----+------+
    | id | name |
    +----+------+
    |  2 | A    |
    |  4 | B    |
    +----+------+
    2 rows in set (0.00 sec)
    
    mysql> insert into t_order(name) values("E");
    Query OK, 1 row affected (0.00 sec)
    
    mysql> select * from t_order;
    +----+------+
    | id | name |
    +----+------+
    |  2 | A    |
    |  4 | B    |
    |  5 | E    |
    +----+------+
    3 rows in set (0.00 sec)
    

    可以发现master1中id的步长为2,且从1开始自增,再去master2中查询能发现id为5的数据,说明主主复制配置没有问题。

    为什么两个主中id自增的偏移量要不一致呢?当两个主同时接受到插入请求时就能保证id不冲突,其实这样只能保证插入数据不冲突,无法保证删除和修改导致的数据不一致。

    所以在实际的应用场景中,只能暴露一个主给客户端才能保证数据的一致性。

    MySQL高可用的搭建

    image-20220209185303569

    这里借助keepalived来对上面的多主复制架构改造来实现MySQL的高可用。

    keepalived的安装:

    $ sudo apt-get install -y keepalived
    

    keepalived.conf

    $ cat /etc/keepalived/keepalived3314.conf
    ! Configuration File for keepalived
    #简单的头部,这里主要可以做邮件通知报警等的设置,此处就暂不配置了;
    global_defs {
            #notificationd LVS_DEVEL
    }
    #预先定义一个脚本,方便后面调用,也可以定义多个,方便选择;
    vrrp_script chk_haproxy {
        script "/etc/keepalived/chkmysql.sh"  #具体脚本路径
        interval 2  #脚本循环运行间隔
    }
    #VRRP虚拟路由冗余协议配置
    vrrp_instance VI_1 {   #VI_1 是自定义的名称;
        state BACKUP    #MASTER表示是一台主设备,BACKUP表示为备用设备【我们这里因为设置为开启不抢占,所以都设置为备用】
        nopreempt      #开启不抢占
        interface eth0   #指定VIP需要绑定的物理网卡
        virtual_router_id 11   #VRID虚拟路由标识,也叫做分组名称,该组内的设备需要相同
        priority 130   #定义这台设备的优先级 1-254;开启了不抢占,所以此处优先级必须高于另一台
    
        advert_int 1   #生存检测时的组播信息发送间隔,组内一致
        authentication {    #设置验证信息,组内一致
            auth_type PASS   #有PASS 和 AH 两种,常用 PASS
            auth_pass asd    #密码
        }
        virtual_ipaddress {
            172.23.252.200    #指定VIP地址,组内一致,可以设置多个IP
        }
        track_script {    #使用在这个域中使用预先定义的脚本,上面定义的
            chk_haproxy
        }
    
        #notify_backup "/etc/init.d/haproxy restart"   #表示当切换到backup状态时,要执行的脚本
        #notify_fault "/etc/init.d/haproxy stop"     #故障时执行的脚本
    }
    

    /etc/keepalived/chkmysql.sh

    $ cat /etc/keepalived/chkmysql.s.sh
    #!/bin/bash
    
    mysql -uroot -proot -P 3314 -e "show status;" > /dev/null 2>&1
    
    if [ $? == 0 ];
    then
            echo "$host mysql login successfully"
            exit 0
    else
            echo "$host login failed"
            killall keepalived
            exit 2
    fi
    
    展开全文
  • MySQL 数据库——主从复制与读写分离

    万次阅读 多人点赞 2021-11-01 02:08:19
    文章目录前言一、MySQL主从复制1.支持的复制类型2.主从复制的工作过程是基于日志3.请求方式4.主从复制的原理5.MySQL集群和主从复制分别适合在什么场景下使用6.为什么使用主从复制、读写分离7.用途及条件8.mysql主从...

    前言

    在实际的生产环境中,如果对MySQL数据库的读和写都在一台数据库服务中操作,无论在安全性、高可用性,还是高并发性等各个方面都是完全不能满足实际需求的,一般来说都是通过主从复制(Master-Slave)的方式来同步数据,再通过读写分离来提升数据库的并发负载能力这样的方案进行部署与实施

    一、MySQL主从复制

    1.支持的复制类型

    • 基于语句的复制(statement):在服务器上执行sql语句,在从服务器上执行同样的语句,mysql默认采用基于语句的复制,执行效率高
    • 基于行的复制(row): 把改变的内容复制过去,而不是把命令在从服务器上执行一遍
    • 混合类型的复制(mixed): 在服务器上执行sql语句,在从服务器上执行同样的语句,mysql默认采用基于语句的复制,执行效率高

    2.主从复制的工作过程是基于日志

    • master二进制日志
    • slave中继日志

    3.请求方式

    • I/O线程
    • dump线程
    • SQL线程

    4.主从复制的原理

    ①Master节点将数据的改变记录成二进制日志(bin log),当Master上的数据发生改变时,则将其改变写入二进制日志中

    ②Slave节点会在一定时间间隔内对Master的二进制日志进行探测其是否发生改变,如果发生改变,则开始一个I/O线程请求 Master的二进制事件

    ③同时Master节点为每个I/O线程启动一个dump线程,用于向其发送二进制事件,并保存至Slave节点本地的中继日志(Relay log)中

    ④Slave节点将启动SQL线程从中继日志中读取二进制日志,在本地重放,即解析成 sql 语句逐一执行,使得其数据和 Master节点的保持一致,最后I/O线程和SQL线程将进入睡眠状态,等待下一次被唤醒

    复制过程有一个很重要的限制,即复制在 Slave 上是串行化的,也就是说 Master 上的并行更新操作不能在 Slave 上并行操作

    中继日志通常会位于OS缓存中,所以中继日志的开销很小

    mark

    5.MySQL集群和主从复制分别适合在什么场景下使用

    集群和主从复制是为了应对高并发、大访问量的情况,如果网站访问量和并发量太大了,少量的数据库服务器是处理不过来的,会造成网站访问慢,数据写入会造成数据表或记录被锁住,锁住的意思就是其他访问线程暂时不能读写要等写入完成才能继续,这样会影响其他用户读取速度,采用主从复制可以让一些服务器专门读,一些专门写可以解决这个问题

    6.为什么使用主从复制、读写分离

    主从复制、读写分离一般是一起使用的,目的很简单,就是为了提高数据库的并发性能。你想,假设是单机,读写都在一台MySQL上面完成,性能肯定不高。如果有三台MySQL,一台mater只负责写操作,两台salve只负责读操作,性能不就能大大提高了吗?

    所以主从复制、读写分离就是为了数据库能支持更大的并发

    随着业务量的扩展、如果是单机部署的MySQL,会导致I/O频率过高。采用主从复制、读写分离可以提高数据库的可用性

    7.用途及条件

    mysql主从复制用途:

    • 实时灾备,用于故障切换
    • 读写分离,提供查询服务
    • 备份,避免影响服务

    必要条件:

    • 主库开启binlog日志(设置log-bin参数)
    • 主从server-id不同
    • 从库服务器能连通主库

    8.mysql主从复制存在的问题

    主库宕机后,数据可能丢失

    从库只有一个SQL Thread,主库写压力大,复制很可能延时

    解决办法

    半同步复制——解决数据丢失的问题

    并行复制——解决从库复制延迟的问题

    9.MySQL主从复制延迟

    ①master服务器高并发,形成大量事务
    ②网络延迟
    ③主从硬件设备导致——cpu主频、内存io、硬盘io
    ④本来就不是同步复制、而是异步复制

    • 从库优化Mysql参数。比如增大innodb_buffer_pool_size,让更多操作在Mysql内存中完成,减少磁盘操作
    • 从库使用高性能主机,包括cpu强悍、内存加大。避免使用虚拟云主机,使用物理主机,这样提升了i/o方面性
    • 从库使用SSD磁盘
    • 网络优化,避免跨机房实现同步

    二、主从复制的形式

    mark

    mark

    mark

    三、读写分离

    1.原理

    ①只在主服务器上写,只在从服务器上读

    ②主数据库处理事务性查询,从数据库处理select查询

    ③数据库复制用于将事务性查询导致的变更同步到集群中的从数据库

    mark

    2.为什么要读写分离呢?

    • 因为数据库的“写”(写10000条数据可能要3分钟)操作是比较耗时的
    • 但是数据库的“读”(读10000条数据可能只要5秒钟)
    • 所以读写分离,解决的是,数据库的写入,影响了查询的效率

    3.什么时候要读写分离?

    • 数据库不一定要读写分离,如果程序使用数据库较多时,而更新少,查询多的情况下会考虑使用
    • 利用数据库主从同步,再通过读写分离可以分担数据库压力,提高性能

    4.主从复制与读写分离

    • 在实际的生产环境中,对数据库的读和写都在同一个数据库服务器中,是不能满足实际需求的

    5.目前较为常见的MySQL读写分离分为以下两种

    ①基于程序代码内部实现

    • 在代码中根据 select、insert 进行路由分类,这类方法也是目前生产环境应用最广泛的
    • 优点是性能较好,因为在程序代码中实现,不需要增加额外的设备为硬件开支;缺点是需要开发人员来实现,运维人员无从下手
    • 但是并不是所有的应用都适合在程序代码中实现读写分离,像一些大型复杂的Java应用,如果在程序代码中实现读写分离对代码改动就较大

    ②基于中间代理层实现

    代理一般位于客户端和服务器之间,代理服务器接到客户端请求后通过判断后转发到后端数据库,有以下代表性程序
    (1)MySQL-Proxy,MySQL-Proxy 为 MySQL 开源项目,通过其自带的 lua 脚本进行SQL 判断。
    (2)Atlas,是由奇虎360的Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目,它是在mysql-proxy 0.8.2版本的基础上,对其进行了优化,增加了一些新的功能特性。360内部使用Atlas运行的mysql业务,每天承载的读写请求数达几十亿条。支持事物以及存储过程
    (3)Amoeba,由陈思儒开发,作者曾就职于阿里巴巴。该程序由Java语言进行开发,阿里巴巴将其用于生产环境。但是它不支持事务和存储过程。

    • 由于使用MySQL Proxy 需要写大量的Lua脚本,这些Lua并不是现成的,而是需要自己去写,这对于并不熟悉MySQL Proxy 内置变量和MySQL Protocol 的人来说是非常困难的
    • Amoeba是一个非常容易使用、可移植性非常强的软件。因此它在生产环境中被广泛应用于数据库的代理层

    四、案例实施

    1.案例环境

    • 本案例环境使用舞台服务器磨你搭建,拓扑图如下

    mark

    主机名主机操作系统IP 地址主要软件
    CentOS 7-1MasterCentOS 7192.168.126.11ntp 、 mysql-boost-5.7.17.tar.gz
    CentOS 7-2AmoebaCentOS 7192.168.126.12jdk-6u14-linux-x64.bin、amoeba-mysql-binary-2.2.0.tar.gz
    CentOS 7-3Slave1CentOS 7192.168.126.13ntp 、ntpdate 、 mysql-boost-5.7.20.tar.gz
    CengOS 7-4Slave2CentOS 7192.168.126.14ntp 、ntpdate 、mysql-boost-5.7.17.tar.gz
    CentOS 7-5客户端CentOS 7-5192.168.126.15mysql5.7

    2.实验思路(解决需求)

    1. 客户端访问代理服务器
    2. 代理服务器写入到主服务器
    3. 主服务器将增删改写入自己二进制日志
    4. 从服务器将主服务器的二进制日志同步至自己中继日志
    5. 从服务器重放中继日志到数据库中
    6. 客户端读,则代理服务器直接访问从服务器
    7. 降低负载,起到负载均衡作用

    3.准备

    • 除了客户端,都需要先源码编译安装好MySQL
    • 都需关闭防火墙及控制访问机制
    systemctl stop firewalld
    systemctl disable firewalld
    #关闭防火墙(及开机禁用)
    setenforce 0
    #关闭安全访问控制机制
    

    4.搭建MySQL主从复制

    ①Mysql主从服务器时间同步

    • 主服务器设置
    #安装 NTP
    yum -y install ntp
    
    
    #配置 NTP
    vim /etc/ntp.conf
    #末行添加以下内容
    server 127.127.126.0
    fudge 127.127.126.0 stratum 8
    
    #设置本地是时钟源,注意修改网段
    #设置时间层级为8(限制在15内)
    
    
    
    #重启服务
    service ntpd restart
    
    • 从服务器设置
    yum -y install ntp ntpdate
    #安装服务,ntpdate用于同步时间
    
    service ntpd start
    #开启服务
    
    
    /usr/sbin/ntpdate 192.168.126.11
    #进行时间同步,指向Master服务器IP
    
    
    crontab -e
    #写入计划性任务,每半小时进行一次时间同步
    */30 * * * * /usr/sbin/ntpdate 192.168.126.11
    

    ②配置MySQL Master主服务器

    vim /etc/my.cnf
    #配置以下内容
    
    server-id = 1
    log-bin=master-bin
    #添加,主服务器开启二进制日志
    log-slave-updates=true
    #添加,允许从服务器更新二进制日志
    
    
    systemctl restart mysqld
    #重启服务使配置生效
    
    
    mysql -uroot -p123123
    #登录数据库程序,给从服务器授权
    GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.126.%' IDENTIFIED BY '123123';
    FLUSH PRIVILEGES;
    
    show master status;
    quit
    
    #File 列显示日志名,Fosition 列显示偏移量
    

    mark

    mark

    ③配置从服务器

    vim /etc/my.cnf
    server-id = 2
    
    #修改,注意id与Master的不同,两个Slave的id也要不同
    relay-log=relay-log-bin
    #添加,开启中继日志,从主服务器上同步日志文件记录到本地
    relay-log-index=slave-relay-bin.index
    #添加,定义中继日志文件的位置和名称
    
    
    systemctl restart mysqld
    
    
    mysql -uroot -p123123
    change master to master_host='192.168.126.11' , master_user='myslave',master_password='123123',master_log_file='master-bin.000001',master_log_pos=604;
    #配置同步,注意 master_log_file 和 master_log_pos 的值要与Master的一致
    
    start slave;
    #启动同步,如有报错执行 reset slave;
    show slave status\G
    #查看 Slave 状态
    //确保 IO 和 SQL 线程都是 Yes,代表同步正常
    
    
    Slave_IO_Running: Yes
    #负责与主机的io通信
    Slave_SQL_Running: Yes
    #负责自己的slave mysql进程
    
    • slave1:

    mark

    mark

    mark

    • slave2: 和slave1配置一样,id不能相同

    mark

    mark

    • 一般 Slave_IO_Running: No 有这几种可能性:
      • 网络不通
      • my.cnf 配置有问题
      • 密码、file 文件名、pos 偏移量不对
      • 防火墙没有关闭

    ④验证主从复制效果

    mark

    mark

    mark

    5.搭建MySQL读写分离

    • 这个软件致力于 MySQL 的分布式数据库前端代理层,它主要为应用层访问 MySQL 时充当 SQL 路由,并具有负载均衡、高可用性、SQL 过滤、读写分离、可路由相关到目标数据库、可并发请求多台数据库
    • 通过 Amoeba 能够完成多数据源的高可用、负载均衡、数据切片的功能

    ①在主机Amoeba上安装Java环境

    • 因为 Amoeba 基于是 jdk1.5 开发的,所以官方推荐使用 jdk1.5 或 1.6 版本,高版本不建议使用
    cd /opt/
    #在FinalShell中,把软件包拖进来
    amoeba-mysql-binary-2.2.0.tar.gz
    jdk-6u14-linux-x64.bin
    
    cp jdk-6u14-linux-x64.bin /usr/local/
    
    cd /usr/local/
    chmod +x jdk-6u14-linux-x64.bin
    ./jdk-6u14-linux-x64.bin
    #按住Enter键不动一直到最下面,有提示输入YES+回车即可
    
    
    mv jdk1.6.0_14/ /usr/local/jdk1.6
    #改名
    
    vim /etc/profile
    #编辑全局配置文件,在最后一行添加以下配置
    export JAVA_HOME=/usr/local/jdk1.6
    export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
    export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin
    export AMOEBA_HOME=/usr/local/amoeba
    export PATH=$PATH:$AMOEBA_HOME/bin
    
    #输出定义Java的工作目录
    #输出指定的java类型
    #将java加入路径环境变量
    #输出定义amoeba工作目录
    #加入路径环境变量
    
    
    source /etc/profile
    #执行修改后的全局配置文件
    java -version
    #查看java版本信息以检查是否安装成功
    

    ②安装并配置Amoeba

    mkdir /usr/local/amoeba
    tar zxvf /opt/amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
    chmod -R 755 /usr/local/amoeba/
    /usr/local/amoeba/bin/amoeba
    
    #如显示 amoeba start|stop 说明安装成功
    

    mark

    ③配置Amowba读写分离,两个slave读写负载均衡

    • 在master、slave1、slave2的mysql上开放权限给amoeba访问
    grant all on *.* to test@'192.168.126.%' identified by '123.com';
    

    mark

    mark

    mark

    ④在主机amoeba中编辑amoeba.xml配置文件

    cd /usr/local/amoeba/conf/
    cp amoeba.xml amoeba.xml.bak
    
    vim amoeba.xml
    #修改amoeba配置文件
    
    #30行修改
    <property name="user">amoeba</property>
    #32行修改
    <property name="password">123123</property>
    #115行修改
    <property name="defaultPool">master</property>
    #117去掉注释
    <property name="writePool">master</property>
    <property name="readPool">slaves</property>
    

    ⑤编辑dbServers.xml 配置文件

    cp dbServers.xml dbServers.xml.bak
    
    vim dbServers.xml
    #修改数据库配置文件
    
    #23行注释掉
    作用:默认进入test库 以防mysql中没有test库时,会报错
    <!-- <property name="schema">test</property> -->
    #26行修改
    <property name="user">test</property>
    #28-30行去掉注释
    <property name="password">123.com</property>
    #45行修改,设置主服务器的名Master
    <dbServer name="master"  parent="abstractServer">
    #48行修改,设置主服务器的地址
    <property name="ipAddress">192.168.126.11</property>
    #52行修改,设置从服务器的名slave1
    <dbServer name="slave1"  parent="abstractServer">
    #55行修改,设置从服务器1的地址
    <property name="ipAddress">192.168.126.13</property>
    #58行复制上面6行粘贴,设置从服务器2的名slave2和地址
    <dbServer name="slave2"  parent="abstractServer">
    <property name="ipAddress">192.168.184.14</property>
    #65行修改
    <dbServer name="slaves" virtual="true">
    #71修改
    <property name="poolNames">slave1,slave2</property>
    

    ⑥确定配置无误后,可以启动 Amoeba 软件,其默认端口为 tcp 8066

    /usr/local/amoeba/bin/amoeba start&
    #启动Amoeba软件,按ctrl+c 返回
    netstat -anpt | grep java
    #查看8066端口是否开启,默认端口为TCP 8066
    

    ⑦测试

    1. 前往客户端快速装好 MySQL 虚拟客户端,然后通过代理访问 MySQL
    yum -y install mysql
    #用YUM快速安装MySQL虚拟客户端
    
    mysql -u amoeba -p123123 -h 192.168.126.12 -P8066
    #通过代理访问MySQL,IP地址指向amoba
    #在通过客户端连接mysql后写入的数据只有主服务会记录,然后同步给从服务器
    

    2.在 Master 上创建一个表,同步到两个从服务器上

    use club;
    create table puxin (id int(10),name varchar(10),address varchar(20));
    

    3.然后关闭从服务器的 Slave 功能,从主服务器上同步了表,手动插入数据内容

    stop slave;
    #关闭同步
    
    use club;
    insert into puxin values('1','wangyi','this_is_slave1');
    
    
    #slave2
    insert into puxin values('2','wanger','this_is_slave2');
    

    4.再回到主服务器上插入其他内容

    insert into pucin values('3','wangwu','this_is_master');
    

    5.测试读操作,前往客户端主机查询结果

    use club;
    select * from puxin;
    

    6.在客户端上插入一条语句,但是在客户端上查询不到,最终只有在 Master 上才上查看到这条语句内容,说明写操作在 Master 服务器上

    insert into puxin values('4','liuliu','this_is_client');
    

    7.再在两个从服务器上执行 start slave; 即可实现同步在主服务器上添加的数据

    总结

    • 由此验证,已经实现了 MySQL 读写分离,目前所有的写操作全部在 Master 主服务器上,用来避免数据的不同步
    • 而所有的读操作都分摊给了 Slave 从服务器,用来分担数据库的压力

    1.如何查看主从同步状态是否成功

    • 在从服务器内输入命令 show slave status\G,查看主从信息进行查看,里面有IO线程的状态信息,还有master服务器的IP地址、端口、事务开始号
    • 当 slave_io_running 和 slave_sql_running 都显示为yes时,表示主从同步状态成功

    2.如果I/O和SQL不是yes呢,你是如何排查的

    • 首先排除网络问题,使用ping命令查看从服务是否能与主服务器通信
    • 再者查看防火墙和核心防护是否关闭
    • 接着查看从服务器内的slave是否开启
    • 两个从服务器的 server-id 是否相同导致只能连上一台
    • master_log_file 和 master_log_pos 的值要是否与Master查询的一致

    3.show slave status能看到哪些信息(比较重要的)

    • IO线程的状态信息
    • master服务器的IP地址、端口、事务开始位置
    • 最近一次的报错信息和报错位置等

    4.主从复制慢(延迟)有哪些可能

    • 主服务器的负载过大,被多个睡眠或者僵尸线程占用,导致系统负载过大
    • 从库硬件比主库差,导致复制延迟
    • 主从复制单线程,如果主库写并发太大,来不及传送到从库,就会导致延迟
    • 慢SQL语句过多
    • 网络延迟
    展开全文
  • 分布式数据复制技术

    万次阅读 2021-12-26 18:30:30
    数据复制技术原理及应用同步复制技术原理及应用异步复制技术原理及应用半同步复制技术原理及应用三种数据复制技术对比知识扩展:在半同步复制技术中,对于未回复数据更新结果的节点,如何解决数据不一致或冲突呢?...


    前言

    数据分布(也称数据分片)技术,主要用于构建数据索引, 是实现“导购”功能的关键技术。数据分布的本质是,将原数据集划分为多个数据子集,以存储到不同的地方,在一定程度上体现了数据的可用性和可靠性(一个存储节点故障,只影响该存储节点的数据)。

    数据分片和数据复制技术均是实现“导购”的关键技术:

    • 数据分片是确定数据位置;
    • 数据复制是实现数据可靠性的关键方法。

    在实际情况下,仅考虑数据分片,其实是无法真正应用到生产环境的。因为,故障导致数据丢失和不可用是很常见的情况。因此,在进行分布式数据存储设计时,通常会考虑对数据进行备份,以提高数据的可用性和可靠性,而实现数据备份的关键技术就是“数据复制技 术”。

    什么是数据复制技术?

    数据复制是一种实现数据备份的技术。比如,现在有节点 1 和节点 2,节点 1 上存储了 10M 用户数据,数据复制技术就是将节点 1 上的这 10M 数据拷贝到节点 2 上,以使得节点 1 和节点 2 上存储了相同的数据,也就是节点 2 对节点 1 的数据进行了备份。当节点 1 出现故障后,可以通过获取节点 2 上的数据,实现分布式存储系统的自动容错。

    数据复制技术可以保证存储在不同节点上的同一份数据是一致的。当一个节点故障后,可以从其他存储该数据的节点获取数据,避免数据丢失,进而提高了系统的可靠性。

    在分布式数据库系统中,通常会设置主备数据库,当主数据库出现故障时,备数据库可以替代主数据库进行后续的工作,从而保证业务的正常运行。备数据库继续提供服务就是提高了分布式存储系统的可用性及可靠性。

    在这个过程中,实现备数据库替代主数据库,就涉及到数据一致性的问题了,只有主备数据库中的数据保持一致时,才可实现主备的替换。在这个例子中,数据复制技术实际就是指,如何让主备数据库保持数据一致的技术

    数据复制技术原理及应用

    CAP 理论的 C、A 和 P 三个特性,在分布式存储系统中,分区容错性是肯定要满足的,为此需要在一致性和可用性之间做出权衡。所以,对于数据的一致性,通常是指不同节点上数据要保持一致。要实现不同节点上的数据 一致,数据复制技术必不可少。对于分布式存储系统中的数据复制技术来讲,也需要在一致性和可用性之间做出一些权衡。这就导致出现了多种数据复制技术方法,大体上有三类:

    1. 注重一致性,比如同步复制技术;
    2. 注重可用性,比如异步复制技术;
    3. 介于前两者之间的,比如半同步复制技术。

    同步复制技术原理及应用

    同步复制技术:指当用户请求更新数据时,主数据库必须要同步到备数据库之后才可给用户返回,即如果主数据库没有同步到备数据库,用户的更新操作会一直阻塞。这种方式保证了数据的强一致性,但牺牲了系统的可用性。

    在一个分布式数据库系统中,有两个节点,分别作为主节点和备节点。通常情况下,两个节点均可接收用户读请求,然后将本节点的数据及时返回给用户,读请求响应比较快。而如果用户发送的是写请求,写操作必须由主节点进行,即使用户将写请求发送到备节点,备节点也会将该请求转发给主节点,因此写请求通常比读请求响应慢。MySQL 集群的读写分离就是一个典型实例。

    如此设计的原因是,读请求不需要改变数据,只需要在更改数据时保证数据一致,就可以随时读;而写请求,因为要修改数据,如果每个节点均修改同一数据,则可能导致数据不一致。因此只有主节点可以进行写操作,但又要保证主节点和备节点的数据一致,这就是数据复制技术要发挥的作用了。

    对于上述场景,如果采用同步复制技术的话,对于写请求,主数据库会执行写操作,并将数据同步到所有备数据库之后才可以响应用户。如图所示,客户端向主数据库发起更新操作 V,将 X 设置为 2,主数据库会将写请求同步到备数据库,备数据库操作完后会通知主数据库同步成功,然后主数据库才会告诉客户端更新操作成功。MySQL 集群支持的全复制模式就采用了同步复制技术。

    在这里插入图片描述

    在同步复制技术中,主数据库需要等待所有备数据库均操作成功才可以响应用户,会影响用户体验,同步复制技术经常用于分布式数据库主备场景(对于一主多备场景,由于多个备节点均要更新成功后,主节点才响应用于,所需时延比较长)或对数据一致性有严格要求的场合,比如金融、交易之类的场景。

    异步复制技术原理及应用

    异步复制技术:指当用户请求更新数据时,主数据库处理完请求后可直接给用户响应,不必等待备数据库完成同步,即备数据库会异步进行数据的同步,用户的更新操作不会因为备数据库未完成数据同步而导致阻塞。这种方式保证了系统的可用性,但牺牲了数据的一致性。

    如图所示,客户端 1 向主数据库发起更新操作 V,主数据库执行该操作,将 X=1 修改为 X=2,执行后直接返回给客户端 1 更新操作成功,而未将数据同步到备数据库。当客户端 2 请求主数据库的数据 X 时,可以得到 X=2,但客户端 3 请求备数据库中的数据 X 时,却只能得到 X=1,从而导致请求结果不一致。

    在这里插入图片描述

    分布式数据库主备模式场景下,若对数据一致性要求不高,可以采用异步复制方法。MySQL 集群默认的数据复制模式采用的是异步复制技术,以 MySQL 集群默认的复制模式为例,展示主备数据库同步的流程:

    1. 主数据库完成写操作后,可直接给用户回复执行成功,将写操作写入 binary log 中, binary log 中记录着主数据库执行的所有更新操作,以便备数据库获取更新信息。
    2. 备数据库启动一个 IO 线程专门读取 binary log 中的内容然后写入 relay log 中。
    3. 备数据库启动一个 SQL 线程会定时检查 relay log 里的内容,如发现有新内容则会立即在备数据库中执行,从而实现数据的一致。

    在这里插入图片描述

    异步复制技术大多应用在对用户请求响应时延要求很高的场景,比如很多网站或 App 等需要面向实际用户,这时后台的数据库或缓存如果采用同步复制技术,可能会流失用户,因此这种场景采用异步复制技术就比较合适。

    在缓存数据库 Redis 集群中,采用的也是异步复制技术,因此性能较高。但在 Redis 中还会有其他机制来保证数据的一致性。

    半同步复制技术原理及应用

    同步复制技术会满足数据的强一致性,但会牺牲一定的可用性;异步复制技术会满足高可用,但一定程度上牺牲了数据的一致性。介于两者中间的是,半同步复制技术。

    半同步复制技术:用户发出写请求后,主数据库会执行写操作,并给备数据库发送同步请求,但主数据库不用等待所有备数据库回复数据同步成功便可响应用户,主数据库可以等待一部分备数据库同步完成后响应用户写操作执行成功。

    半同步复制技术通常有两种方式:

    1. 主数据库收到多个备数据库中的某一个回复数据同步成功后,便可给用户响应写操作完成;
    2. 主数据库等超过一半节点(包括主数据库)回复数据更新成功后,再给用户响应写操作成功。

    第二种半同步复制方案要求的一致性比第一种要高一些,但相对可用性会低一些。

    MySQL 集群在一主多备场景下,也支持半同步复制模式,一般采用的是第一种半同步复制技术,这种技术既不会影响过多的性能,还可以更好地实现对数据的保护。

    具有 CP 特性的 ZooKeeper 集群采用的数据复制技术就是第二种半同步复制方案。在 ZooKeeper 集群中,写请求必须由 Leader 节点进 行处理,每次写请求 Leader 会征求其他 Follower 的同意,只有当多数节点同意后写操作才可成功,因此保证了较高的一致性。

    还有很多系统采用了第二种半同步复制方案,比如微软云关系型数据库 Microsoft SQL Azure 的后端存储系统 Cloud SQL Server、Kubenetes 中保存集群所有网络配置和对象状态信息的 Etcd 组件(该组件采用的是 Raft 一致性协议)等。

    多数的分布式存储系统可以通过配置来选择不同的数据复制技术。比如 MySQL 数据库集群,就支持全同步复制、异步复制和半同步复制三种模式,再比如 Oracle 数据库,也提供了三种模式:

    • 最大保护模式,对于写请求,要求主数据库必须完成至少一个备数据库的数据同步才可成功返回给客户端,采用的是半同步复制技术中的第一种方式。
    • 最大性能模式,对于写请求,只要主数据库执行成功即可返回给客户端,采用的是异步复制技术。这种方式极大地提高了系统的可用性,但一致性难以保证。
    • 最大可用性模式,介于最大保护模式和最大性能模式两者之间。系统在通常情况下采用最大保护模式,但当主备之间出现网络故障时,切换为最大性能模式, 等到网络恢复后,备数据库再进行数据同步。这种方式在系统的一致性和可用性之间做了一个权衡。

    三种数据复制技术对比

    在这里插入图片描述

    知识扩展:在半同步复制技术中,对于未回复数据更新结果的节点,如何解决数据不一致或冲突呢?

    对于半同步复制技术,因为只有部分备节点更新数据后,主节点即可返回响应用户。对于未回复数据更新结果的节点,可能存在的数据不一致或冲突。

    不同的场景有不同的处理方式,需要根据用户的需求进行选择,比如以最新数据为准、以最大数据为准等,没有统一的评判规则,和用户的需求紧密相关。

    在分布式系统中,很多系统采用了 Raft 算法。Raft 算法采用的是第二种半同步复制技术,主数据库等超过一半节点 (包括主数据库)回复数据更新成功后,再给用户响应写操作成功。当有 Follower 节点的数据与 Leader 节点数据不一致时,采用强制复制策略来解决不一致情况。

    由于所有的数据更新操作最先在 Leader 节点执行,因此当产生冲突时,以 Leader 节点为准。Leader 节点上会对比与自己数据不一致的 Follower 节点所存储的信息,找到两者最后达成一致的地方,然后强制将这个地方之后的数据复制到该 Follower 节点上。

    具体方法:Leader 节点将每一次数据操作看作一条记录,并对这条记录标记一个 index,用于索引。Leader 节点会为每个 Follower 节点维护一个记录状态变量 nextIndex,即下一个记录的索引位置(nextIndex 的值为 Leader 节点当前存储数据记录的下一个 Index 值)。Leader 节点会将 nextIndex 发送给 Follower 节点,若 Follower 节点发现与本节点的 nextIndex 不一致,则告知 Leader 节点不一致,Leader 节点将 nextIndex 减 1,重复上述过程,直到与 Follower 节点的 nextIndex 相等位置,即找到了两者最后达成一致的地方。

    比如,对于变量 X,Leader 节点记录的操作是{(Index 1, X = 1, Version:0), (Index 2, X=2, Version:1), (Index3 , X=3, Version:2)},其中,Follower 节点 2 记录的操作为 {(Index 2, X=1, Version:0), (Index 6, X=4, Version:2)}。Leader 节点发现两者最后一致的状态是 {(Index 1, X=1, Version:0)},为此将后续的 {(Index 2, X=2, Version:1), (Index 3, X=3, Version:2)}复制到节点 2 上,则节点 2 更新为 (Index 1, X = 1, Version: 0), (Index 2, X=2, Version:1), (Index3 , X=3, Version:2)}。节点 2 与 Leader 节点的数据保持一致。

    总结

    在这里插入图片描述

    展开全文
  • Redis主从复制原理

    万次阅读 2021-01-10 23:26:24
    一、为什么需要主从复制: 1、单台Redis节点的局限性: (1)单节点的Redis能够支撑QPS大概在5万左右,如果上千万的用户访问,Redis就承载不了,成为了高并发的瓶颈。 (2)内存上,单个Redis的内存不宜过大,...
  • 不是会员不让复制粘贴?看我“三板斧”!

    千次阅读 多人点赞 2021-05-09 18:43:25
    不知道你有没有过这样的经历,我们在网上好不容易搜索到自己想要的内容,复制粘贴时,却被网站要求注册或者购买VIP会员,非常得令人生气和无奈。今天,我们就来介绍一个非常好用的方法来解决这一系列问题。 正文 ...
  • M1卡工具集,包括UID,复制,改写

    千次下载 热门讨论 2014-12-12 15:18:34
    单纯M1,S50,IC卡工具大全集(不含NFC,红外等,如需要,本人资源中有RF全集里包括了所有的而且有文档,本资源不含文档) │ ACS EasyKey.exe │ │ ACS Mifare key Management Tool.exe │ │ ASCII码随心换V3.0....
  • redis主从之全量复制及增量复制

    千次阅读 2020-06-04 00:15:22
    对于主从复制的好处,在上篇文章我也写了,下面说一下注意事项。 注意事项: 安全 对于数据比较重要的节点,主节点会通过设置requirepass参数进行密码验证,这时候所有的客户端访问必须使用auth命令进行验证。从...
  • 同步复制与异步复制

    万次阅读 2021-06-21 10:36:30
    主从复制:其中一种设计,包括一个同步的从节点,和一个异步的从节点。 从节点2在接收复制日志之前有一段很长的延迟。通常情况下,复制速度会非常快,例如多数数据库系统可以在一秒之内完成所有从节点的更新。但是,...
  • Redis——Redis主从复制(工作流程详解)

    万次阅读 多人点赞 2021-04-18 20:53:12
    Redis主从复制主从复制简介主从复制的概念主从复制的作用主从复制工作流程阶段一:建立连接阶段主从连接(slave连接master)第一种方式第二种方式第三种方式授权访问阶段二:数据同步阶段工作流程数据同步阶段master...
  • MySQL主从复制 原理:将主服务器的binlog日志复制到从服务器上执行一遍,达到主从数据的一致状态。 过程:从库开启一个I/O线程,向主库请求Binlog日志。主节点开启一个binlog dump线程,检查自己的二进制日志,...
  • eclipse快速复制一行代码的快捷键是什幺步骤一:通过快捷键“ctrl+alt+向下箭头”复制上面一行代码。步骤二:按住“alt+向上或向下箭头”移动本行代码向上或向下移动,点击箭头一次,移动一行。效果如下图。写代码的...
  • vim 复制粘贴

    千次阅读 2022-04-02 15:03:24
    1.复制和粘贴整行 我们都知道复制的快捷键是“nyy”,粘贴的快捷键是“p”。 Tips 1.“yy” 是复制光标所在行,“nyy”是复制包括光标所在行以及向下的“n-1”行**,一共n行。 2. “p”是将已经复制的数据,粘贴在...
  • 空格网名符号复制

    万次阅读 2021-06-14 06:13:25
    空格网名符号复制搜狗输入法,v+1 在按下d 就是空格 :这里空格【】 这里还有一个空格: []弄了,在游戏里就是空白名空格符号复制法一:搜狗输入法将半角转换全角,快捷键(Shift+空格键),按空格(根据:半角空格...
  • java文件复制方法Java copy file is a very common operation. But java.io.File class doesn’t have any shortcut method to copy a file from source to destination. Here we will learn about four different ...
  • 【MySQL】主从复制实现原理详解

    千次阅读 多人点赞 2020-02-25 23:41:27
    1.1 mysql复制的优点 1.2 Mysql复制解决的问题 二、MySQL 主从复制的概念 三、MySQL 主从复制的主要用途 3.1 读写分离 3.2 数据实时备份,当系统中某个节点发生故障时,可以方便的故障切换(主从切换) 3.3 高...
  • 今天来解决百度文库的复制问题,有些时候,比如做毛概,思修,伦理学的作业,就要经常复制百度文库的答案,但是百度要恰饭 ,所以无法直接复制(如图) 但是因为html的一些特性,或者是百度自己提供的功能,我们...
  • 以制作目录页为例,通常地,我们会进行如下操作:❶ 选中❷ 复制❸ 重复粘贴多次❹ 分别移动到大致位置❺ 选中所有,依次点击【格式】-【对齐】中的【左对齐】和【纵向分布】两个选项……最后,替换其中的内容,并...
  • 现在,很多用户在使用电脑的过程中都会用到复制粘贴功能,特别是对于上班族来说更为重要。不过,有些用户在Win7系统中使用复制粘贴功能复制粘贴文字时发现该功能失效,导致操作失败。那么,遇到这问题时该怎么来处理...
  • 快速复制 在excel中,Ctrl + D有快速复制的功能,首先输入一个内容,接着直接按Ctrl + D,就可以快速输入上面同样的内容。 普通操作是输入后往下拖动,然后选择复制单元格,如图: 其实也可以用快捷键Ctrl + D即可...
  • 目录: strcpy() 举例: memcpy() 举例: strncpy() 举例: memmove() 举例: 我们首先来考虑一个简单的问题,我们定义了一个字符串,然后想要复制这个字符串,在C语言中,我们可以用for循环和指针来实现,假如我们用...
  • 批量复制文件夹,不复制内容

    千次阅读 2020-11-24 17:33:27
    这时候我们就需要只复制文件夹,不复制内容。那么,到底怎样只复制文件夹,不复制内容呢? 此时,无论是批量建立文件夹,手动修改名称,还是将内部的文件一同复制,再逐个删除,显然都太费时费力; 经过查找和尝试...
  • 一、MongoDB复制集原理 (一)复制集简介 (二)复制集节点介绍 二、MongoDB复制集搭建 (一)MongoDB配置文件配置 (二)MongoDB复制集配置文件配置 (三)MongoDB复制集初始化启动 三、...
  • 使用Nginx实现多重流量复制

    千次阅读 2022-03-15 17:32:37
    使用Nginx实现流量复制
  • 将加密门禁卡复制到手机或者手环上的几种方法。
  • 电脑,一个无论是生活还是学习,以及工作等等都会用到的用具,所以掌握一些基本的操作是必要的,例如我们在使用电脑时,难免会需要复制粘贴一些文字,这时我们可以使用复制粘贴快捷键来解决,不过知道的用户有几个?...
  • 缘起 最近写一个程序,需要操作...poi操作excel,复制sheet,复制行,复制单元格 使用POI操作Excel:Sheet拷贝 POI导出Excel时设置单元格类型为数值类型 问题 如果在copy一个cell的时候,需要把样式也copy过去,怎...
  • 网页中无法复制的文字如何复制

    千次阅读 2021-11-27 14:57:19
    在浏览网页时经常遇到想要复制又不能复制的文字,其实是前端的一种遮罩层,如何复制? 解决办法:右键 ->检查 进入开发者模式,按如图123的步骤,选择定位到要复制的文字,右键取消隐藏元素,Hide element ...
  • linux复制命令

    千次阅读 2021-12-07 10:54:59
    cp 命令既可以复制文件,也可以复制目录。我们先来看看如何复制文件,例如: [root@localhost ~]# touch cangls #建立源文件 [root@localhost ~]# cp cangls /tmp/ #把源文件不改名复制到 /tmp/ 目录下 如果需要...
  • vi 整行 多行 复制与粘贴

    千次阅读 2021-05-16 09:50:53
    1、复制1)单行复制在命令模式下,将光标移动到将要复制的行处,按“yy”进行复制;2)多行复制在命令模式下,将光标移动到将要复制的首行处,按“nyy”复制n行;其中n为1、2、3……2、粘贴在命令模式下,将光标移动到...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,906,436
精华内容 1,562,574
关键字:

复制