Golang进阶,揉碎数据库中间件,干货满满!
2021/11/28 19:10:59
本文主要是介绍Golang进阶,揉碎数据库中间件,干货满满!,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
目录- 必读
- 一、Centos7、Mac安装MySQL
- 二、主从复制原理
- 2.1、基于binlog_filename + position
- 2.2、基于GTID
- 三、my.cnf
- 四、测试SQL
- 五、中间件使用、概念串讲
- 六、总揽启动流程
- 七、权限管理实现原理
- 八、MySQL协议-Handshake!和中间件握手机制原理
- 九、中间件不断接受处理客户端SQL原理
- 十、中间件是如何执行你的select语句的?
- 十一、读写分离实现原理
- 十二、赠送Proxy源码
必读
欢迎关注白日梦的公众号(风一样的程序员)回复:数据库中间件 。
即可获取写有注释的中间件源码包,开箱即用~
一、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
搞明白这几点:
- 跟大家讲明白这样一件事,你以为你是直连的MySQL?其实不是的,你直连的MySQL_Proxy
- Node、分片的概念
- Proxy配置文件的解读
- 演示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管理依赖包,开箱即用~
关注白日梦的公众号(风一样的程序员),回复:数据库中间件 ,即可领取当前文档以及源码包。
这篇关于Golang进阶,揉碎数据库中间件,干货满满!的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-15SendGrid 的 Go 客户端库怎么实现同时向多个邮箱发送邮件?-icode9专业技术文章分享
- 2024-11-15SendGrid 的 Go 客户端库怎么设置header 和 标签tag 呢?-icode9专业技术文章分享
- 2024-11-12Cargo deny安装指路
- 2024-11-02MongoDB项目实战:从入门到初级应用
- 2024-11-01随时随地一键转录,Google Cloud 新模型 Chirp 2 让语音识别更上一层楼
- 2024-10-25Google Cloud动手实验详解:如何在Cloud Run上开发无服务器应用
- 2024-10-24AI ?先驱齐聚 BAAI 2024,发布大规模语言、多模态、具身、生物计算以及 FlagOpen 2.0 等 AI 模型创新成果。
- 2024-10-20goland工具下,如修改一个项目的标准库SDK的版本-icode9专业技术文章分享
- 2024-10-17Go学习:初学者的简单教程
- 2024-10-17Go学习:新手入门完全指南