主頁 > 後端開發 > MySQL高可用架構(MHA)與Atlas讀寫分離

MySQL高可用架構(MHA)與Atlas讀寫分離

2020-12-15 07:15:12 後端開發

file

1.1 MHA簡介

1.1.1 MHA軟體介紹

  MHA(Master High Availability)目前在MySQL高可用方面是一個相對成熟的解決方案,它由日本DeNA公司youshimaton(現就職于Facebook公司)開發,是一套優秀的作為MySQL高可用性環境下故障切換和主從提升的高可用軟體,在MySQL故障切換程序中,MHA能做到在10~30秒之內自動完成資料庫的故障切換操作,并且在進行故障切換的程序中,MHA能在最大程度上保證資料的一致性,以達到真正意義上的高可用,

  MHA能夠在較短的時間內實作自動故障檢測和故障轉移,通常在10-30秒以內;在復制 框架中,MHA能夠很好地解決復制程序中的資料一致性問題,由于不需要在現有的 replication中添加額外的服務器,僅需要一個manager節點,而一個Manager能管理多套復制,所以能大大地節約服務器的數量;另外,安裝簡單,無性能損耗,以及不需要修改現 有的復制部署也是它的優勢之處,

  MHA還提供在線主庫切換的功能,能夠安全地切換當前運行的主庫到一個新的主庫中 (通過將從庫提升為主庫),大概0.5-2秒內即可完成,

  該軟體由兩部分組成:MHA Manager(管理節點)和MHA Node(資料節點),MHA Manager可以單獨部署在一臺獨立的機器上管理多個master-slave集群,也可以部署在一臺slave節點上,MHA Node運行在每臺MySQL服務器上,MHA Manager會定時探測集群中的master節點,master出現故障時,它可以自動將最新資料的slave提升為新的master,然后將所有其他的slave重新指向新的master整個故障轉移程序對應用程式完全透明,

  在MHA自動故障切換程序中,MHA試圖從宕機的主服務器上保存二進制日志,最大程度的保證資料的不丟失,但這并不總是可行的,例如,如果主服務器硬體故障或無法通過ssh訪問,MHA沒法保存二進制日志,只進行故障轉移而丟失了最新的資料,使用MySQL 5.5的半同步復制,可以大大降低資料丟失的風險,

  MHA可以與半同步復制結合起來,如果只有一個slave已經收到了最新的二進制日志,MHA可以將最新的二進制日志應用于其他所有的slave服務器上,因此可以保證所有節點的資料一致性,

  目前MHA主要支持一主多從的架構,要搭建MHA,要求一個復制集群中必須最少有三臺資料庫服務器,一主二從,即一臺充當master,一臺充當備用master,另外一臺充當從庫,因為至少需要三臺服務器,出于機器成本的考慮,淘寶也在該基礎上進行了改造,目前淘寶TMHA已經支持一主一從,

1.1.2 MHA作業原理

file 作業原理說明: 1、保存master上的所有binlog事件 2、找到含有最新binlog位置點的slave 3、通過中繼日志將資料恢復到其他的slave 4、將包含最新binlog位置點的slave提升為master 5、將其他從庫slave指向新的master原slave01 并開啟主從復制 6、將保存下來的binlog恢復到新的master上

1、監控所有node節點MHA功能說明:

2、自動故障切換(failover)

前提是必須有三個節點存在,并且有兩個從庫

  (1)選主前提,按照組態檔的順序進行,但是如果此節點后主庫100M以上relay-log 就不會選

  (2)如果你設定了權重,總會切換帶此節點;一般在多地多中心的情況下,一般會把權重設定在本地節點,

  (3)選擇s1為新主

  (4)保存主庫binlog日志

3、重新構建主從

  (1)將有問題的節點剔除MHA

    進行第一階段資料補償,S2缺失部分補全90

  (2)s1切換角色為新主,將s2指向新主S1

     s2 change master to s1

  (3) 第二階段資料補償

     將保存過來的新主和原有主缺失部分的binlog,應用到新主,

  (4)虛擬IP漂移到新主,對應用透明無感知

   (5)通知管理員故障切換

1.1.3 MHA高可用架構圖

file

1.1.4 MHA工具介紹

  MHA軟體由兩部分組成,Manager工具包和Node工具包,具體的說明如下:

  Manager工具包主要包括以下幾個工具:

masterha_check_ssh             #檢査 MHA 的 ssh-key^
masterha_check_repl            #檢査主從復制情況
masterha_manger                #啟動MHA
masterha_check_status          #檢測MHA的運行狀態^
masterha_mast er_monitor       #檢測master是否宕機一
masterha_mast er_switch        #手動故障轉移—
masterha_conf_host             #手動添加server倍息一
masterha_secondary_check       #建立TCP連接從遠程服務器v
masterha_stop                  #停止MHA

Node工具包主要包括以下幾個工具:

save_binary_1ogs       #保存宕機的master的binlog
apply_diff_relay_logs   #識別relay log的差異
filter_mysqlbinlog           #防止回滾事件一MHA已不再使用這個工具
purge_relay_logs           #清除中繼曰志一不會阻塞SQL執行緒

1.1.5 MHA的優點

1、自動故障轉移

2、主庫崩潰不存在資料不一致的情況

3、不需要對當前的mysql環境做重大修改

4、不需要添加額外的服務器

5、性能優秀,可以作業再半同步和異步復制框架

6、只要replication支持的存盤引擎mha都支持

1.2 環境說明

   在本次的實驗中,共需要用到三臺主機,系統、軟體說明如下,

1.2.1 系統環境說明

db01主機(master)

[root@db01 ~]# cat /etc/redhat-release 
CentOS release 6.9 (Final)
[root@db01 ~]# uname -r
2.6.32-696.el6.x86_64
[root@db01 ~]# /etc/init.d/iptables status
iptables: Firewall is not running.
[root@db01 ~]# getenforce 
Disabled
[root@db01 ~]# hostname -I
10.0.0.51 172.16.1.51

db02主機(slave1)

 1 [root@db02 ~]# cat /etc/redhat-release 
 2 CentOS release 6.9 (Final)
 3 [root@db02 ~]# uname -r
 4 2.6.32-696.el6.x86_64
 5 [root@db02 ~]# /etc/init.d/iptables status
 6 iptables: Firewall is not running.
 7 [root@db02 ~]# getenforce 
 8 Disabled
 9 [root@db02 ~]# hostname -I
10 10.0.0.52 172.16.1.52

db03主機(slave1,MHA Manages、Atlas節點)

 1 [root@db02 ~]# cat /etc/redhat-release 
 2 CentOS release 6.9 (Final)
 3 [root@db02 ~]# uname -r
 4 2.6.32-696.el6.x86_64
 5 [root@db02 ~]# /etc/init.d/iptables status
 6 iptables: Firewall is not running.
 7 [root@db02 ~]# getenforce 
 8 Disabled
 9 [root@db02 ~]# hostname -I
10 10.0.0.52 172.16.1.52

1.2.2 mysql軟體說明

? 三臺服務器上都全新安裝mysql 5.6.36 :

[root@db01 ~]# mysql --version
mysql  Ver 14.14 Distrib 5.6.36, for Linux (x86_64) using  EditLine wrapper

  關于mysql資料庫具體的安裝方法參考:http://www.cnblogs.com/clsn/p/8038964.html#_label3

1.3 基于GTID的主從復制配置

1.3.1 先決條件

  ?? 主庫和從庫都要開啟binlog

  ?? 主庫和從庫server-id必須不同

  ?? 要有主從復制用戶

1.3.2 配置主從復制

db01 my.cnf****檔案

[root@db01 ~]# cat /etc/my.cnf
[mysqld]
basedir=/application/mysql
datadir=/application/mysql/data
socket=/tmp/mysql.sock
log-error=/var/log/mysql.log
log-bin=/data/mysql/mysql-bin
binlog_format=row
secure-file-priv=/tmp 
server-id=51
skip-name-resolve  # 跳過域名決議
gtid-mode=on    # 啟用gtid型別,否則就是普通的復制架構
enforce-gtid-consistency=true    #強制GTID的一致性
log-slave-updates=1     # slave更新是否記入日志(5.6必須的)
relay_log_purge = 0 
[mysql]
socket=/tmp/mysql.sock

db02 my.cnf****檔案

 1 [root@db02 ~]# cat /etc/my.cnf
 2 [mysqld]
 3 basedir=/application/mysql
 4 datadir=/application/mysql/data
 5 socket=/tmp/mysql.sock
 6 log-error=/var/log/mysql.log
 7 log-bin=/data/mysql/mysql-bin
 8 binlog_format=row
 9 secure-file-priv=/tmp 
10 server-id=52
11 skip-name-resolve
12 gtid-mode=on
13 enforce-gtid-consistency=true
14 log-slave-updates=1
15 relay_log_purge = 0 
16 [mysql]
17 socket=/tmp/mysql.sock

db03 my.cnf****檔案

 1 [root@db03 ~]# cat /etc/my.cnf
 2 [mysqld]
 3 basedir=/application/mysql
 4 datadir=/application/mysql/data
 5 socket=/tmp/mysql.sock
 6 log-error=/var/log/mysql.log
 7 log-bin=/data/mysql/mysql-bin
 8 binlog_format=row
 9 secure-file-priv=/tmp 
10 server-id=53
11 skip-name-resolve
12 gtid-mode=on
13 enforce-gtid-consistency=true
14 log-slave-updates=1
15 relay_log_purge = 0 
16 skip-name-resolve
17 [mysql]
18 socket=/tmp/mysql.sock

創建復制用戶 (51作為主節點,52、53為從)

GRANT REPLICATION SLAVE ON *.* TO repl@'10.0.0.%' IDENTIFIED BY '123';

從庫開啟復制

change master to 
    master_host='10.0.0.51',
    master_user='repl',
    master_password='123',
    MASTER_AUTO_POSITION=1;

啟動從庫復制

start slave;

1.3.3 GTID復制技術說明

MySQL GTID****簡介

  GTID的全稱為 global transaction identifier ,可以翻譯為全域事務標示符,GTID在原始master上的事務提交時被創建,GTID需要在全域的主-備拓撲結構中保持唯一性,GTID由兩部分組成:

 GTID = source_id:transaction_id

  source_id用于標示源服務器,用server_uuid來表示,這個值在第一次啟動時生成,并寫入到組態檔data/auto.cnf中

  transaction_id則是根據在源服務器上第幾個提交的事務來確定,

GTID**事件結構

file
GTID**在二進制日志中的結構

file
一個GTID*的生命周期包括:*

1.事務在主庫上執行并提交給事務分配一個gtid(由主庫的uuid和該服務器上未使用的最小事務序列號),該GTID被寫入到binlog中,

2.備庫讀取relaylog中的gtid,并設定session級別的gtid_next的值,以告訴備庫下一個事務必須使用這個值

3.備庫檢查該gtid是否已經被其使用并記錄到他自己的binlog中,slave需要擔保之前的事務沒有使用這個gtid,也要擔保此時已分讀取gtid,但未提交的事務也不恩呢過使用這個gtid.

4.由于gtid_next非空,slave不會去生成一個新的gtid,而是使用從主庫獲得的gtid,這可以保證在一個復制拓撲中的同一個事務gtid不變,由于GTID在全域的唯一性,通過GTID,我們可以在自動切換時對一些復雜的復制拓撲很方便的提升新主庫及新備庫,例如通過指向特定的GTID來確定新備庫復制坐標,

    GTID是用來替代以前classic的復制方法;

    MySQL5.6.2支持 MySQL5.6.10后完善;

GTID****相比傳統復制的優點:

1.一個事務對應一個唯一ID,一個GTID在一個服務器上只會執行一次

2.GTID是用來代替傳統復制的方法,GTID復制與普通復制模式的最大不同就是不需要指定二進制檔案名和位置

3.減少手工干預和降低服務故障時間,當主機掛了之后通過軟體從眾多的備機中提升一臺備機為主機

GTID****的限制:

1.不支持非事務引擎

2.不支持create table ... select 陳述句復制(主庫直接報錯)

  原理:( 會生成兩個sql,一個是DDL創建表SQL,一個是insert into 插入資料的sql,

  由于DDL會導致自動提交,所以這個sql至少需要兩個GTID,但是GTID模式下,只能給這個sql生成一個GTID )  

3.不允許一個SQL同時更新一個事務引擎表和非事務引擎表

4.在一個復制組中,必須要求統一開啟GTID或者是關閉GTID

5.開啟GTID需要重啟(5.7除外)

6.開啟GTID后,就不再使用原來的傳統復制方式

7.對于create temporary table 和 drop temporary table陳述句不支持

8.不支持sql_slave_skip_counter

1.3.4 COM_BINLOG_DUMP_GTID

從機發送到主機執行的事務的識別符號的主范圍

   Master send all other transactions to slave

  同樣的GTID不能被執行兩次,如果有同樣的GTID,會自動被skip掉,

file
  slave1:將自己的UUID1:1發送給master,然后接收到了UUID1:2,UUID1:3 event

  slave2:將自己的UUID1:1,UUID1:2發送給master,然后接收到了UUID1:3事件

GTID****組成

  GTID實際上是由UUID+TID組成的,其中UUID是一個MySQL實體的唯一標識,TID代表了該實體上已經提交的事務數量,并且隨著事務提交單調遞增

GTID = source_id :transaction_id
7E11FA47-31CA-19E1-9E56-C43AA21293967:29

1.3.5 【示例二】MySQL GTID復制配置

主節點my.cnf檔案

# vi /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/data/mysql
server-id=1
log-bin=mysql-bin
socket=/tmp/mysql.sock
binlog-format=ROW
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1

從節點my.cnf檔案

# vi /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/data/mysql
server-id=2
binlog-format=ROW
gtid-mode=on
enforce-gtid-consistency=true
log-bin=mysql-bin
log_slave_updates = 1
socket=/tmp/mysql.sock

組態檔注解

server-id=x                    # 同一個復制拓撲中的所有服務器的id號必須惟一
binlog-format=RO               # 二進制日志格式,強烈建議為ROW
gtid-mode=on                   # 啟用gtid型別,否則就是普通的復制架構
enforce-gtid-consistency=true  # 強制GTID的一致性
log-slave-updates=1            # slave更新是否記入日志

  復制用戶準備(Master主節點)

mysql>GRANT REPLICATION SLAVE ON *.* TO rep@'10.0.0.%' IDENTIFIED BY '123';

  開啟復制(Slave從節點)

mysql>start slave;
mysql>show slave status\G

  現在就可以進行主從復制測驗,

1.4 部署MHA

  本次MHA的部署基于GTID復制成功構建,普通主從復制也可以構建MHA架構,

1.4.1 環境準備(所有節點操作)

安裝依賴包

yum install perl-DBD-MySQL -y

   下載mha軟體,mha官網:https://code.google.com/archive/p/mysql-master-ha/

? github下載地址:https://github.com/yoshinorim/mha4mysql-manager/wiki/Downloads

*下載軟體包*

mha4mysql-manager-0.56-0.el6.noarch.rpm

mha4mysql-manager-0.56.tar.gz

mha4mysql-node-0.56-0.el6.noarch.rpm

mha4mysql-node-0.56.tar.gz

在所有節點安裝node

rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm

創建mha管理用戶

grant all privileges on *.* to mha@'10.0.0.%' identified by 'mha';

# 主庫上創建,從庫會自動復制(在從庫上查看)

  創建命令軟連接(重要)

  如果不創建命令軟連接,檢測mha復制情況的時候會報錯

ln -s /application/mysql/bin/mysqlbinlog /usr/bin/mysqlbinlog
ln -s /application/mysql/bin/mysql /usr/bin/mysql

1.4.2 部署管理節點(mha-manager)

在mysql-db03上部署管理節點

# 安裝epel源,軟體需要
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo 
# 安裝manager 依賴包
yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes
# 安裝manager管理軟體
rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm

創建必須目錄

mkdir -p /etc/mha
mkdir -p /var/log/mha/app1    ----》可以管理多套主從復制

編輯mha-manager*組態檔*

[root@db03 ~]# cat  /etc/mha/app1.cnf
[server default]                        
manager_log=/var/log/mha/app1/manager
manager_workdir=/var/log/mha/app1
master_binlog_dir=/data/mysql
user=mha
password=mha
ping_interval=2
repl_password=123
repl_user=repl
ssh_user=root

[server1]
hostname=10.0.0.51
port=3306

[server2]
hostname=10.0.0.52
port=3306

[server3]
hostname=10.0.0.53
port=3306

【組態檔詳解】

 [server default]
 2 #設定manager的作業目錄
 3 manager_workdir=/var/log/masterha/app1
 4 #設定manager的日志
 5 manager_log=/var/log/masterha/app1/manager.log 
 6 #設定master 保存binlog的位置,以便MHA可以找到master的日志,我這里的也就是mysql的資料目錄
 7 master_binlog_dir=/data/mysql
 8 #設定自動failover時候的切換腳本
 9 master_ip_failover_script= /usr/local/bin/master_ip_failover
10 #設定手動切換時候的切換腳本
11 master_ip_online_change_script= /usr/local/bin/master_ip_online_change
12 #設定mysql中root用戶的密碼,這個密碼是前文中創建監控用戶的那個密碼
13 password=123456
14 #設定監控用戶root
15 user=root
16 #設定監控主庫,發送ping包的時間間隔,嘗試三次沒有回應的時候自動進行failover
17 ping_interval=1
18 #設定遠端mysql在發生切換時binlog的保存位置
19 remote_workdir=/tmp
20 #設定復制用戶的密碼
21 repl_password=123456
22 #設定復制環境中的復制用戶名 
23 repl_user=rep
24 #設定發生切換后發送的報警的腳本
25 report_script=/usr/local/send_report
26 #一旦MHA到server02的監控之間出現問題,MHA Manager將會嘗試從server03登錄到server02
27 secondary_check_script= /usr/local/bin/masterha_secondary_check -s server03 -s server02 --user=root --master_host=server02 --master_ip=10.0.0.51 --master_port=3306
28 #設定故障發生后關閉故障主機腳本(該腳本的主要作用是關閉主機放在發生腦裂,這里沒有使用)
29 shutdown_script=""
30 #設定ssh的登錄用戶名
31 ssh_user=root 
32 
33 [server1]
34 hostname=10.0.0.51
35 port=3306
36 
37 [server2]
38 hostname=10.0.0.52
39 port=3306
40 #設定為候選master,如果設定該引數以后,發生主從切換以后將會將此從庫提升為主庫,即使這個主庫不是集群中事件最新的slave
41 candidate_master=1
42 #默認情況下如果一個slave落后master 100M的relay logs的話,MHA將不會選擇該slave作為一個新的master,因為對于這個slave的恢復需要花費很長時間,通過設定check_repl_delay=0,MHA觸發切換在選擇一個新的master的時候將會忽略復制延時,這個引數對于設定了candidate_master=1的主機非常有用,因為這個候選主在切換的程序中一定是新的master
43 check_repl_delay=0

配置ssh信任(密鑰分發,在所有節點上執行)

# 生成密鑰
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1
# 分發公鑰,包括自己
for i in 1 2 3 ;do ssh-copy-id -i /root/.ssh/id_dsa.pub [email protected]$i ;done

? 分發完成后測驗分發是否成功

for i in 1 2 3 ;do ssh 10.0.0.5$i  date ;done
或
[root@db03 ~]# masterha_check_ssh --conf=/etc/mha/app1.cnf
最后一行資訊為如下字樣即為分發成功:
Thu Dec 28 18:44:53 2017 - [info] All SSH connection tests passed successfully.

1.4.3 啟動mha

經過上面的部署過后,mha架構已經搭建完成

# 啟動mha
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &

? 啟動成功后,檢查主庫狀態

[root@db03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf 
app1 (pid:3298) is running(0:PING_OK), master:10.0.0.51

1.4.4 切換master測驗

查看現在的主庫是哪個

[root@db03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf 
app1 (pid:11669) is running(0:PING_OK), master:10.0.0.51

手動停止主庫

[root@db01 ~]# /etc/init.d/mysqld stop 
Shutting down MySQL..... SUCCESS!

再停止資料的同時查看日志資訊的變化

[root@db03 ~]# tailf /var/log/mha/app1/manager
~~~
Fri Dec 29 15:51:14 2017 - [info]  All other slaves should start replication from
here. Statement should be: CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='xxx';

修復主從

① 啟動原主庫,添加change master to 資訊

[root@db01 ~]# /etc/init.d/mysqld start 
Starting MySQL. SUCCESS!
mysql> CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';
mysql> start slave;

② 查看主從復制狀態

mysql> show slave status\G
                   Master_Host: 10.0.0.52
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

修復mha

① 修改app1.cnf組態檔,添加回被剔除主機

[root@db03 ~]# cat  /etc/mha/app1.cnf 
[binlog1]
hostname=10.0.0.53
master_binlog_dir=/data/mysql/binlog/
no_master=1

[server default]
manager_log=/var/log/mha/app1/manager
manager_workdir=/var/log/mha/app1
master_binlog_dir=/data/mysql
master_ip_failover_script=/usr/local/bin/master_ip_failover
password=mha
ping_interval=2
repl_password=123
repl_user=repl
ssh_user=root
user=mha

[server1]
hostname=10.0.0.51
port=3306

[server2]
hostname=10.0.0.52
port=3306

[server3]
hostname=10.0.0.53
port=3306

② mha檢查復制狀態

[root@db03 ~]# masterha_check_repl --conf=/etc/mha/app1.cnf
MySQL Replication Health is OK.

③ 啟動mha程式

nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &

到此主庫切換成功

[root@db03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf 
app1 (pid:11978) is running(0:PING_OK), master:10.0.0.52

實驗結束將主庫切換回db01.

① 停止mha

[root@db03 ~]# masterha_stop --conf=/etc/mha/app1.cnf 
Stopped app1 successfully.

② 停止所有從庫slave(所有庫操作)

stop slave;
reset slave all;

③ 重做主從復制(db02、db03)

CHANGE MASTER TO 
  MASTER_HOST='10.0.0.51', 
  MASTER_PORT=3306, 
  MASTER_AUTO_POSITION=1, 
  MASTER_USER='repl', 
  MASTER_PASSWORD='123';

④ 啟動slave

start slave;

? 啟動之后檢查從庫是否為兩個yes show slave status\G

⑤ mha檢查主從復制

[root@db03 ~]# masterha_check_repl --conf=/etc/mha/app1.cnf
MySQL Replication Health is OK.

⑥ 啟動mha

nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &

  檢查切換是否成功

[root@db03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:12127) is running(0:PING_OK), master:10.0.0.51

? 到此主主節點有切回到db01

1.4.5 設定權重

修改[server1]的權重

[server1]
hostname=10.0.0.51
port=3306
candidate_master=1
check_repl_delay=0

配置說明

candidate_master=1                  ----》不管怎樣都切到優先級高的主機,一般在主機性能差異的時候用           
check_repl_delay=0                  ----》不管優先級高的備選庫,資料延時多久都要往那切

注:

1、多地多中心,設定本地節點為高權重

2、在有半同步復制的環境中,設定半同步復制節點為高權重

3、你覺著哪個機器適合做主節點,配置較高的 、性能較好的

1.5 配置VIP漂移

1.5.1 IP漂移的兩種方式

 ?? 通過keepalived的方式,管理虛擬IP的漂移

   ?? 通過MHA自帶腳本方式,管理虛擬IP的漂移

1.5.2 MHA腳本方式

修改mha****組態檔

[root@db03 ~]# grep "script" /etc/mha/app1.cnf 
[server default]
master_ip_failover_script=/usr/local/bin/master_ip_failover

? 再主配置中添加VIP腳本

腳本內容

[root@db03 ~]# cat /usr/local/bin/master_ip_failover 
#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';
use Getopt::Long;
my (
    $command,          $ssh_user,        $orig_master_host, $orig_master_ip,
    $orig_master_port, $new_master_host, $new_master_ip,    $new_master_port
);
my $vip = '10.0.0.55/24';
my $key = '0';
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";

GetOptions(
    'command=s'          => \$command,
    'ssh_user=s'         => \$ssh_user,
    'orig_master_host=s' => \$orig_master_host,
    'orig_master_ip=s'   => \$orig_master_ip,
    'orig_master_port=i' => \$orig_master_port,
    'new_master_host=s'  => \$new_master_host,
    'new_master_ip=s'    => \$new_master_ip,
    'new_master_port=i'  => \$new_master_port,
);

exit &main();

sub main {

    print "\n\nIN SCRIPT TEST====$ssh_stop_vip==$ssh_start_vip===\n\n";

    if ( $command eq "stop" || $command eq "stopssh" ) {

        my $exit_code = 1;
        eval {
            print "Disabling the VIP on old master: $orig_master_host \n";
            &stop_vip();
            $exit_code = 0;
        };
        if ($@) {
            warn "Got Error: $@\n";
            exit $exit_code;
        }
        exit $exit_code;
    }
    elsif ( $command eq "start" ) {

        my $exit_code = 10;
        eval {
            print "Enabling the VIP - $vip on the new master - $new_master_host \n";
            &start_vip();
            $exit_code = 0;
        };
        if ($@) {
            warn $@;
            exit $exit_code;
        }
        exit $exit_code;
    }
    elsif ( $command eq "status" ) {
        print "Checking the Status of the script.. OK \n";
        exit 0;
    }
    else {
        &usage();
        exit 1;
    }
}

sub start_vip() {
    `ssh $ssh_user\@$new_master_host \" $ssh_start_vip \"`;
}
sub stop_vip() {
     return 0  unless  ($ssh_user);
    `ssh $ssh_user\@$orig_master_host \" $ssh_stop_vip \"`;
}

sub usage {
    print
    "Usage: master_ip_failover --command=start|stop|stopssh|status --orig_master_host=host --orig_master_ip=ip --orig_master_port=port --new_master_host=host --new_master_ip=ip --new_master_port=port\n";
}

  該腳本為軟體自帶,腳本獲取方法:再mha原始碼包中的samples目錄下有該腳本的模板,對該模板進行修改即可使用,路徑如: mha4mysql-manager-0.56/samples/scripts

  腳本修改內容

my $vip = '10.0.0.55/24';
my $key = '0';
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";

腳本添加執行權限否則mha無法啟動

chmod +x /usr/local/bin/master_ip_failover

手動系結VIP(****主庫)

ifconfig eth0:0 10.0.0.55/24

  檢查

[root@db01 ~]# ip a s eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:6c:7a:11 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.51/24 brd 10.0.0.255 scope global eth0
    inet 10.0.0.55/24 brd 10.0.0.255 scope global secondary eth0:0
    inet6 fe80::20c:29ff:fe6c:7a11/64 scope link 
       valid_lft forever preferred_lft forever

? 至此vip****漂移配置完成

1.5.3 測驗虛擬IP漂移

查看db02的slave資訊

img View Code 現在主從狀態

停掉主庫

[root@db01 ~]# /etc/init.d/mysqld stop

在db03上查看從庫slave資訊

img View Code 停掉主庫后的主從資訊

在db01上查看vip資訊

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:6c:7a:11 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.51/24 brd 10.0.0.255 scope global eth0
    inet6 fe80::20c:29ff:fe6c:7a11/64 scope link 
       valid_lft forever preferred_lft forever

在db02上查看vip資訊

 [root@db02 ~]# ip a s eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:d6:0a:b3 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.52/24 brd 10.0.0.255 scope global eth0
inet 10.0.0.55/24 brd 10.0.0.255 scope global secondary eth0:0
    inet6 fe80::20c:29ff:fed6:ab3/64 scope link 
       valid_lft forever preferred_lft forever

? 至此,VIP漂移就測驗成功

1.6 配置binlog-server

1.6.1 配置binlog-server

1)前期準備:

1、準備一臺新的mysql實體(db03),GTID必須開啟,

2、將來binlog接收目錄,不能和主庫binlog目錄一樣

2)停止mha

masterha_stop --conf=/etc/mha/app1.cnf

3)在app1.cnf開啟binlogserver功能

    [binlog1]
    no_master=1
    hostname=10.0.0.53                         ----> 主機DB03
    master_binlog_dir=/data/mysql/binlog/  ----> binlog保存目錄

4)開啟binlog接收目錄,注意權限

mkdir -p /data/mysql/binlog/ 
chown -R mysql.mysql /data/mysql
# 進入目錄啟動程式
  cd /data/mysql/binlog/ &&\
  mysqlbinlog  -R --host=10.0.0.51 --user=mha --password=mha --raw  --stop-never mysql-bin.000001 &

  引數說明:-R 遠程主機

5)啟動mha

nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &

1.6.2 測驗binlog備份

#查看binlog目錄中的binlog

[root@db03 binlog]# ll
total 44
-rw-r--r-- 1 root root 285 Mar  8 03:11 mysql-bin.000001

#登錄主庫

[root@mysql-db01 ~]# mysql -uroot -p123

#重繪binlog

mysql> flush logs;

#再次查看binlog目錄

[root@db03 binlog]# ll
total 48
-rw-r--r-- 1 root root 285 Mar  8 03:11 mysql-bin.000001
-rw-r--r-- 1 root root 143 Mar  8 04:00 mysql-bin.000002

1.7 mysql中間件Atlas

1.7.1 atlas簡介

  Atlas是由 Qihoo 360公司Web平臺部基礎架構團隊開發維護的一個基于MySQL協議的資料中間層專案,它在MySQL官方推出的MySQL-Proxy 0.8.2版本的基礎上,修改了大量bug,添加了很多功能特性,目前該專案在360公司內部得到了廣泛應用,很多MySQL業務已經接入了Atlas平臺,每天承載的讀寫請求數達幾十億條,

  同時,有超過50家公司在生產環境中部署了Atlas,超過800人已加入了我們的開發者交流群,并且這些數字還在不斷增加,而且安裝方便,配置的注釋寫的蠻詳細的,都是中文,

  Atlas官方鏈接: https://github.com/Qihoo360/Atlas/blob/master/README_ZH.md

  Atlas下載鏈接: https://github.com/Qihoo360/Atlas/releases

1.7.2 主要功能

  讀寫分離、從庫負載均衡、自動分表、IP過濾

  SQL陳述句黑白名單、DBA可平滑上下線DB、自動摘除宕機的DB

Atlas相對于官方MySQL-Proxy的優勢

1.將主流程中所有Lua代碼用C重寫,Lua僅用于管理介面

2.重寫網路模型、執行緒模型

3.實作了真正意義上的連接池

4.優化了鎖機制,性能提高數十倍

1.7.3 使用場景

  Atlas是一個位于前端應用與后端MySQL資料庫之間的中間件,它使得應用程式員無需再關心讀寫分離、分表等與MySQL相關的細節,可以專注于撰寫業務邏輯,同時使得DBA的運維作業對前端應用透明,上下線DB前端應用無感知,

file
  Atlas是一個位于應用程式與MySQL之間中間件,在后端DB看來,Atlas相當于連接它的客戶端,在前端應用看來,Atlas相當于一個DB,

  Atlas作為服務端與應用程式通訊,它實作了MySQL的客戶端和服務端協議,同時作為客戶端與MySQL通訊,它對應用程式屏蔽了DB的細節,同時為了降低MySQL負擔,它還維護了連接池.

1.7.4 企業讀寫分離及分庫分表其他方案介紹

Mysql-proxy(oracle)

Mysql-router(oracle)

Atlas (Qihoo 360)

Atlas-sharding (Qihoo 360)

Cobar(是阿里巴巴(B2B)部門開發)

Mycat(基于阿里開源的Cobar產品而研發)

TDDL Smart Client的方式(淘寶)

Oceanus(58同城資料庫中間件)

OneProxy(原支付寶首席架構師樓方鑫開發 )

vitess(谷歌開發的資料庫中間件)

Heisenberg(百度)

TSharding(蘑菇街白輝)

Xx-dbproxy(金山的Kingshard、當當網的sharding-jdbc )

amoeba

1.7.5 安裝Atlas

  軟體獲取地址:https://github.com/Qihoo360/Atlas/releases

注意:

1、Atlas只能安裝運行在64位的系統上

2、Centos 5.X安裝 Atlas-XX.el5.x86_64.rpm,Centos 6.X安裝Atlas-XX.el6.x86_64.rpm,

3、后端mysql版本應大于5.1,建議使用Mysql 5.6以上

  Atlas (普通) : Atlas-2.2.1.el6.x86_64.rpm

  Atlas (分表) : Atlas-sharding_1.0.1-el6.x86_64.rpm

下載安裝atlas

wget https://github.com/Qihoo360/Atlas/releases/download/2.2.1/Atlas-2.2.1.el6.x86_64.rpm
rpm -ivh Atlas-2.2.1.el6.x86_64.rpm

? 至此安裝完成

1.7.6 配置Atlas組態檔

  atlas組態檔中的密碼需要加密,可以使用,軟體自帶的加密工具進行加密

cd /usr/local/mysql-proxy/conf/
/usr/local/mysql-proxy/bin/encrypt  密碼      ---->制作加密密碼

生產密文密碼:

[root@db03 bin]# /usr/local/mysql-proxy/bin/encrypt 123
3yb5jEku5h4=
[root@db03 bin]# /usr/local/mysql-proxy/bin/encrypt mha
O2jBXONX098=

編輯組態檔

vim  /usr/local/mysql-proxy/conf/test.cnf
[mysql-proxy]
admin-username = user
admin-password = pwd
proxy-backend-addresses = 10.0.0.55:3306
proxy-read-only-backend-addresses = 10.0.0.52:3306,10.0.0.53:3306
pwds = repl:3yb5jEku5h4=,mha:O2jBXONX098=
daemon = true
keepalive = true
event-threads = 8
log-level = message
log-path = /usr/local/mysql-proxy/log
sql-log=ON
proxy-address = 0.0.0.0:33060
admin-address = 0.0.0.0:2345
charset=utf8

組態檔內為全中文注釋,這里有一份較為詳細的解釋:

img View Code Atlas組態檔說明

1.7.7 啟動Atlas

撰寫一個atlas的管理腳本,當然也可以寫腳本,可以直接手動的管理:

/usr/local/mysql-proxy/bin/mysql-proxyd test start   #啟動
/usr/local/mysql-proxy/bin/mysql-proxyd test stop    #停止
/usr/local/mysql-proxy/bin/mysql-proxyd test restart #重啟

  注意:test是組態檔的名稱

腳本內容:

img View Code Atas管理腳本

檢查埠是否正常

[root@db03 ~]# netstat -lntup|grep mysql-proxy
tcp        0      0 0.0.0.0:33060               0.0.0.0:*                   LISTEN      2125/mysql-proxy    
tcp        0      0 0.0.0.0:2345                0.0.0.0:*                   LISTEN      2125/mysql-proxy

1.7.8 Atlas管理操作

  登入管理介面

[root@db03 ~]# mysql -uuser -ppwd -h127.0.0.1 -P2345

  查看幫助資訊

mysql> SELECT * FROM help;

  查看后端的代理庫

mysql> SELECT * FROM backends;
+-------------+----------------+-------+------+
| backend_ndx | address        | state | type |
+-------------+----------------+-------+------+
|           1 | 10.0.0.55:3306 | up    | rw   |
|           2 | 10.0.0.52:3306 | up    | ro   |
|           3 | 10.0.0.53:3306 | up    | ro   |
+-------------+----------------+-------+------+
3 rows in set (0.00 sec)

  平滑摘除mysql

mysql>  REMOVE BACKEND 2;
Empty set (0.00 sec)

   檢查是否摘除

mysql> SELECT * FROM backends;
+-------------+----------------+-------+------+
| backend_ndx | address        | state | type |
+-------------+----------------+-------+------+
|           1 | 10.0.0.55:3306 | up    | rw   |
|           2 | 10.0.0.53:3306 | up    | ro   |
+-------------+----------------+-------+------+
2 rows in set (0.00 sec)

  保存到組態檔中

mysql> SAVE CONFIG;

  將節點再添加回來

mysql> add slave 10.0.0.52:3306;
Empty set (0.00 sec)

  查看是否添加成功

mysql> SELECT * FROM backends;
+-------------+----------------+-------+------+
| backend_ndx | address        | state | type |
+-------------+----------------+-------+------+
|           1 | 10.0.0.55:3306 | up    | rw   |
|           2 | 10.0.0.53:3306 | up    | ro   |
|           3 | 10.0.0.52:3306 | up    | ro   |
+-------------+----------------+-------+------+
3 rows in set (0.00 sec)

 保存到組態檔中

mysql> SAVE CONFIG;

1.7.9 連接資料庫查看負載

通過atlas登陸資料,注意,使用的是資料庫上的用戶及密碼

shell> mysql -umha -pmha -h127.0.0.1 -P33060

第一次查詢server_id

mysql> show variables like "server_id";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 53    |
+---------------+-------+
1 row in set (0.00 sec)

第二次查詢server_id

mysql> show variables like "server_id";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 52    |
+---------------+-------+
1 row in set (0.00 sec)

? *通過上面可以看到負載成功*

1.7.10 讀寫分離的說明

  Atlas會透明的將事務陳述句和寫陳述句發送至主庫執行,讀陳述句發送至從庫執行,具體以下陳述句會在主庫執行:

顯式事務中的陳述句

autocommit=0時的所有陳述句

含有select GET_LOCK()的陳述句

除SELECT、SET、USE、SHOW、DESC、EXPLAIN外的,

從庫負載均衡配置

proxy-read-only-backend-addresses=ip1:port1@權重,ip2:port2@權重

1.7.11 Atlas高級功能

自動分表

  使用Atlas的分表功能時,首先需要在組態檔test.cnf設定tables引數,

tables引數設定格式:資料庫名.表名.分表欄位.子表數量,比如:

你的資料庫名叫school,表名叫stu,分表欄位叫id,總共分為2張表,那么就寫為school.stu.id.2,如果還有其他的分表,以逗號分隔即可,

用戶需要手動建立2張子表(stu_0,stu_1,注意子表序號是從0開始的),

所有的子表必須在DB的同一個database里,

當通過Atlas執行(SELECT、DELETE、UPDATE、INSERT、REPLACE)操作時,Atlas會根據分表結果(id%2=k),定位到相應的子表(stu_k),

例如,執行select * from stu where id=3;,Atlas會自動從stu_1這張子表回傳查詢結果,

但如果執行SQL陳述句(select * from stu;)時不帶上id,則會提示執行stu表不存在,

Atles功能的說明

Atlas暫不支持自動建表和跨庫分表的功能,

Atlas目前支持分表的陳述句有SELECT、DELETE、UPDATE、INSERT、REPLACE,

IP****過濾:client-ips

  該引數用來實作IP過濾功能,

  在傳統的開發模式中,應用程式直接連接DB,因此DB會對部署應用的機器(比如web服務器)的IP作訪問授權,

在引入中間層后,因為連接DB的是Atlas,所以DB改為對部署Atlas的機器的IP作訪問授權,如果任意一臺客戶端都可以連接Atlas,就會帶來潛在的風險,

  client-ips引數用來控制連接Atlas的客戶端的IP,可以是精確IP,也可以是IP段,以逗號分隔寫在一行上即可,

  如: client-ips=192.168.1.2, 192.168.2

  這就代表192.168.1.2這個IP和192.168.2.*這個段的IP可以連接Atlas,其他IP均不能連接,如果該引數不設定,則任意IP均可連接Atlas,如果設定了client-ips引數,且Atlas前面掛有LVS,則必須設定lvs-ips引數,否則可以不設定lvs-ips,

SQL****陳述句黑白名單功能: Atlas會屏蔽不帶where條件的delete和update操作,以及sleep函式,

1.8 Atlas-Sharding版本

1.8.1 版本介紹

  Sharding的基本思想就是把一個資料表中的資料切分成多個部分, 存放到不同的主機上去(切分的策略有多種), 從而緩解單臺機器的性能跟容量的問題.

  sharding是一種水平切分, 適用于單表資料龐大的情景. 目前atlas支持靜態的

  sharding方案, 暫時不支持資料的自動遷移以及資料組的動態加入.

  Atlas以表為單位sharding, 同一個資料庫內可以同時共有sharding的表和不sharding的表, 不sharding的表資料存在未sharding的資料庫組中.

  目前Atlas sharding支持insert, delete, select, update陳述句, 只支持不跨shard的事務. 所有的寫操作如insert, delete, update只能一次命中一個組, 否則會報"ERROR 1105 (HY000):write operation is only allow to one dbgroup!"錯誤.

  由于sharding取替了Atlas的分表功能, 所以在Sharding分支里面, Atlas單機分表的功能已經移除, 配置tables將不會再有效.

1.8.2 Atlas-Sharding架構

file

1.8.3 Sharding配置示例

  Atlas支持非sharding跟sharding的表共存在同一個Atlas中, 2.2.1之前的配置可以直接運行. 之前的配置如

proxy-backend-addresses = 192.168.0.12:3306
proxy-read-only-backend-addresses = 192.168.0.13:3306,192.168.0.14:3306 ... 

  這配置了一個master和兩個slave,這屬于非sharding的組, 所有非sharding的表跟陳述句都會發往這個組內.

  所以之前沒有Sharding的Atlas的表可以無縫的在新版上使用,

? 注意: 非Sharding的組只能配置一個, 而sharding的組可以配置多個. 下面的配置, 配置了Sharding的組, 注意與上面的配置區分

[shardrule-0]
table = test.sharding_test

  分表名,有資料庫+表名組成 t

ype = range

  sharding型別:range 或 hash

shard-key = id

  sharding 欄位

groups = 0:0-999,1:1000-1999

  分片的group,如果是range型別的sharding,則groups的格式是:group_id:id范圍,如果是hash型別的sharding,則groups的格式是:group_id,例如groups = 0, 1

[group-0]
proxy-backend-addresses=192.168.0.15:3306
proxy-read-only-backend-addresses=192.168.0.16:3306
[group-1]
proxy-backend-addresses=192.168.0.17:3306
proxy-read-only-backend-addresses=192.168.0.18:3306

1.8.4 Sharding限制

關于支持的陳述句

  Atlas sharding只對sql陳述句提供有限的支持, 目前支持基本的Select, insert/replace, delete,update陳述句,支持全部的Where語法(SQL-92標準), 不支持DDL(create drop alter)以及一些管理陳述句,DDL請直連MYSQL執行, 請只在Atlas上執行Select, insert, delete, update(CRUD)陳述句.

  對于以下陳述句, 如果陳述句命中了多臺dbgroup, Atlas均未做支持(如果陳述句只命中了一個dbgroup, 如 select count(*) from test where id < 1000, 其中dbgroup0范圍是0 - 1000, 那么這些特性都是支持的)Limit Offset(支持Limit)

Order by

Group by Join

ON

Count, Max, Min等函式

增加節點

  注意: 暫時只支持range方式的節點擴展, hash方式由于需要資料遷移, 暫時未做支持.

  擴展節點在保證原來節點的范圍不改變的情況下, 如已有dbgroup0為范圍0 - 999, dbgroup1為范圍 1000-1999, 這個時候可以增加范圍>2000的節點. 如增加一個節點為2000 - 2999, 修改組態檔, 重啟Atlas即可.

來源:博客園 http://dwz.date/d8qV

歡迎關注公眾號 【碼農開花】一起學習成長
我會一直分享Java干貨,也會分享免費的學習資料課程和面試寶典
回復:【計算機】【設計模式】【面試】有驚喜哦

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/234614.html

標籤:Java

上一篇:Oracle 要慌了!華為終于開源了自家的 Huawei JDK——畢昇 JDK!

下一篇:idea 中使用Mybatis Generator逆向工程生成代碼

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more