Golang進階,揉碎資料庫中介軟體,乾貨滿滿!

賜我白日夢發表於2021-11-28

必讀

歡迎關注白日夢的公眾號(風一樣的程式設計師)回覆:資料庫中介軟體

即可獲取寫有註釋的中介軟體原始碼包,開箱即用~

一、Centos7、Mac安裝MySQL

筆記地址:https://www.cnblogs.com/ZhuChangwu/p/12984153.html

視訊串講地址:https://www.bilibili.com/video/BV19g411N7NR?p=2

二、主從複製原理

2.1、基於binlog_filename + position

原理圖:

筆記地址:https://mp.weixin.qq.com/s/cSToNVQPK8QCpkjapxNoEw

視訊串講地址:https://www.bilibili.com/video/BV19g411N7NR?p=3

2.2、基於GTID

原理圖:

筆記地址:https://mp.weixin.qq.com/s/V5hU2ATeey871loWQIqHKg

視訊串講地址:https://www.bilibili.com/video/BV19g411N7NR?p=4

三、my.cnf

[mysqld]

# 埠
port = 3306

# 資料目錄
datadir=/var/lib/mysql

# 錯誤日誌
log-error=/var/log/mysqld.log

# 為每張表單獨建立一個表空間檔案
# 大家常說的表空間到底是什麼?究竟什麼又是資料表呢? https://mp.weixin.qq.com/s/CwxRjGI843UerF89G_WJ-Q
innodb_file_per_table=on
innodb_file_format = Barracuda

# binlog 相關配置
# 1、MySQL的 bin log有啥用?在哪裡?誰寫的?怎麼配置?
# https://mp.weixin.qq.com/s/DN1shuyxPJ6BkE_RLezAnA

# 2、瞭解bin log的寫入機制嗎?說說你們線上如何調整引數的!
# https://mp.weixin.qq.com/s/MtWzoiJtupso5M8z1KUaQQ

# 3、bin log有哪些格式?有啥區別?優缺點?線上用哪種格式?
# https://mp.weixin.qq.com/s/ar-wVbDi4CYjPI1t6fTjVw
log_bin=mysql-bin
log-bin-index = mysql-bin.index
max_binlog_size = 256M
sync-binlog = 1000
binlog-format = ROW

# relaylog相關配置
relay_log_recovery = 1
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay-log = relay-log
relay-log-index = relay-log.index
sync_relay_log = 1000
max_relay_log_size = 256M

# 設定server-id,叢集唯一
server-id=1

# pid、socket
pid-file=/var/run/mysqld/mysqld.pid
socket=/var/lib/mysql/mysql.sock
symbolic-links=0

四、測試SQL

create database test;
 
use test;

CREATE TABLE `runoob_tbl` (
  `runoob_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `runoob_title` varchar(100) NOT NULL,
  `runoob_author` varchar(40) NOT NULL,
  `submission_date` date DEFAULT NULL,
  PRIMARY KEY (`runoob_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

 INSERT INTO runoob_tbl  (runoob_title, runoob_author, submission_date)
 VALUES("歡迎微信搜尋:", "風一樣的程式設計師", NOW());
CHANGE MASTER TO
    MASTER_HOST='10.4.7.103',
    MASTER_USER='MySQLsync',
    MASTER_PASSWORD='MySQLsync123',
    MASTER_PORT=3306,
    MASTER_AUTO_POSITION = 1;
      
CHANGE MASTER TO
    MASTER_HOST='10.4.7.103',
    MASTER_USER='mysqlsync',
    MASTER_PASSWORD='mysqlsync123',
    MASTER_PORT=3306,
    MASTER_LOG_FILE='mysql-bin.000001',
    MASTER_LOG_POS=434;
    
    CHANGE MASTER TO MASTER_AUTO_POSITION=0; 
 grant replication slave on *.* to MySQLsync@"%" identified by "MySQLsync123";
 
 grant replication slave on *.* to mysqlsync@"127.0.0.1" identified by "mysqlsync123";
 
 grant replication slave on *.* to mysqlsync@"%" identified by "mysqlsync123";

五、中介軟體使用、概念串講

腦圖:

視訊地址:https://www.bilibili.com/video/BV19g411N7NR?p=5

搞明白這幾點:

  1. 跟大家講明白這樣一件事,你以為你是直連的MySQL?其實不是的,你直連的MySQL_Proxy
  2. Node、分片的概念
  3. Proxy配置檔案的解讀
  4. 演示Proxy的使用

六、總攬啟動流程

  • 基於mysql協議獲取主從庫的連線
  • 將主從庫的連線維護進連線池
  • 探活機制

視訊地址:https://www.bilibili.com/video/BV19g411N7NR?p=6

Notice:跟大家講明白這樣一件事,你以為你是直連的MySQL?其實不是的,你直連的MySQL_Proxy!

七、許可權管理實現原理

重點關注的地方:

# server.go:381

// todo 使用者白名單校驗,只有指定的user、ip才能使用Proxy
if allowConnect := conn.IsAllowConnect(); allowConnect == false {
		err := mysql.NewError(mysql.ER_ACCESS_DENIED_ERROR, "ip address access denied by kingshard.")
		conn.writeError(err)
		conn.Close()
		return
	}

視訊地址:https://www.bilibili.com/video/BV19g411N7NR?p=7

八、MySQL協議-Handshake!和中介軟體握手機制原理

原理圖:

重點關注的地方:

server.go:388

  // todo 基於MySQL協議和客戶端建立握手機制
  if err := conn.Handshake(); err != nil {
  	golog.Error("server", "onConn", err.Error(), 0)
 	 	conn.writeError(err)
 	 	conn.Close()
 	  return
  }

backend_conn.go:101



	// todo 這裡其實Proxy和MySQL Server之間建立連線的邏輯
	// todo 大家看到這裡不明白也沒關係,因為想看懂這裡需要了解MySQL協議,後面的視訊中我會跟大家講明白這件事
	// todo 大家只需要知道,執行過這裡的程式碼之後呢,proxy和MySQL-Service之間就會建立一個Conn,
	// todo 並且Proxy會維護這個Conn,後續使用者的SQL打過來之後,Proxy會將使用者的SQL轉發給這裡獲取到的Conn,進爾讓MySQL的引擎去真正的執行這裡的SQL

	// todo 讀MySQL發過來的握手報文
	if err := c.readInitialHandshake(); err != nil {
		c.conn.Close()
		return err
	}
	// todo 寫自己的資訊(port、username、password、host)
	if err := c.writeAuthHandshake(); err != nil {
		c.conn.Close()

		return err
	}
	// todo 讀取MySQL-Server發過來的ok報文
	if _, err := c.readOK(); err != nil {
		c.conn.Close()

		return err
	}

視訊地址:https://www.bilibili.com/video/BV19g411N7NR?p=8

九、中介軟體不斷接受處理客戶端SQL原理

重點關注的地方:

conn.go:279

// todo 下面的程式碼在一個無限迴圈中, 不斷的接受客戶端傳送過來的sql語句
	for {
		// todo 根據MySQL協議解析資料包,獲取出資料包中sql語句
		data, err := c.readPacket()

		if err != nil {
			return
		}

		if c.configVer != c.proxy.configVer {
			err := c.reloadConfig()
			if nil != err {
				golog.Error("ClientConn", "Run",
					err.Error(), c.connectionId,
				)
				c.writeError(err)
				return
			}
			c.configVer = c.proxy.configVer
			golog.Debug("ClientConn", "Run",
				fmt.Sprintf("config reload ok, ver:%d", c.configVer), c.connectionId,
			)
		}
		// 使用dispatch方法,繼續處理資料包
			if err := c.dispatch(data); err != nil {
			c.proxy.counter.IncrErrLogTotal()
			golog.Error("ClientConn", "Run",
				err.Error(), c.connectionId,
			)
			c.writeError(err)
			if err == mysql.ErrBadConn {
				c.Close()
			}
		}

		if c.closed {
			return
		}

		c.pkg.Sequence = 0
	}
}

視訊地址:https://www.bilibili.com/video/BV19g411N7NR?p=9

十、中介軟體是如何執行你的select語句的?

重點關注的地方:

conn.go:279

	// 使用dispatch方法,繼續處理資料包
			if err := c.dispatch(data); err != nil {
			c.proxy.counter.IncrErrLogTotal()
			golog.Error("ClientConn", "Run",
				err.Error(), c.connectionId,
			)
			c.writeError(err)
			if err == mysql.ErrBadConn {
				c.Close()
			}
		}

conn.go:340

func (c *ClientConn) dispatch(data []byte) error {
	c.proxy.counter.IncrClientQPS()
	// todo MYSQL協議規定了,客戶端傳送過來的資料格式是:cmd+data
	// todo 其中的cmd就是sql的型別,型別都列舉在下面了,打眼一看都能懂
	cmd := data[0]
	// todo data部分就是sql詳細內容
	data = data[1:]

	switch cmd {
	case mysql.COM_QUIT:
		c.handleRollback()
		c.Close()
		return nil
	case mysql.COM_QUERY: // todo select 語句
		return c.handleQuery(hack.String(data))
	case mysql.COM_PING: // todo ping 語句
		return c.writeOK(nil)
	case mysql.COM_INIT_DB:
		return c.handleUseDB(hack.String(data))
	case mysql.COM_FIELD_LIST:
		return c.handleFieldList(data)
	case mysql.COM_STMT_PREPARE:
		return c.handleStmtPrepare(hack.String(data))
	case mysql.COM_STMT_EXECUTE:// todo insert、update 語句
		return c.handleStmtExecute(data)
	case mysql.COM_STMT_CLOSE:
		return c.handleStmtClose(data)
	case mysql.COM_STMT_SEND_LONG_DATA:
		return c.handleStmtSendLongData(data)
	case mysql.COM_STMT_RESET:
		return c.handleStmtReset(data)
	case mysql.COM_SET_OPTION:
		return c.writeEOF(0)
	default:
		msg := fmt.Sprintf("command %d not supported now", cmd)
		golog.Error("ClientConn", "dispatch", msg, 0)
		return mysql.NewError(mysql.ER_UNKNOWN_ERROR, msg)
	}

	return nil
}

視訊地址:https://www.bilibili.com/video/BV19g411N7NR?p=10

十一、讀寫分離實現原理

重點關注的地方:

conn_pershard.go:97

	// todo 從選出DB中獲取一條可用的連線,如果是沒有開事物且是讀請求的話,executeDB.IsSlave一般為true
	conn, err := c.getBackendConn(executeDB.ExecNode, executeDB.IsSlave)
	defer c.closeConn(conn, false)
	if err != nil {
		return false, err
	}

視訊地址:https://www.bilibili.com/video/BV19g411N7NR?p=11

十二、贈送Proxy原始碼

寫有註釋的專案已上傳置百度網盤,專案基於vendor管理依賴包,開箱即用~

關注白日夢的公眾號(風一樣的程式設計師),回覆:資料庫中介軟體 ,即可領取當前文件以及原始碼包。

相關文章