zoukankan      html  css  js  c++  java
  • Golang进阶,揉碎数据库中间件,干货满满!

    必读

    欢迎关注白日梦的公众号(风一样的程序员)回复:数据库中间件

    即可获取写有注释的中间件源码包,开箱即用~

    一、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管理依赖包,开箱即用~

    关注白日梦的公众号(风一样的程序员),回复:数据库中间件 ,即可领取当前文档以及源码包。

  • 相关阅读:
    lazy懒载入(延迟载入)UITableView
    POJ 3277 City Horizon
    Effective C++ Item 26 尽可能延后变量定义式的出现时间
    2014 百度之星题解1001
    搭建和測试Android JAVA NDK
    Oracle数据库案例整理-Oracle系统执行时故障-内存过少导致分配共享内存失败
    “以房养老”保险方案为啥行不通?
    Mysql上的RAC:Percona XtraDB Cluster负载均衡集群安装部署手冊
    mysql 数据库查询最后两条数据
    00109_反射概述
  • 原文地址:https://www.cnblogs.com/ZhuChangwu/p/15615195.html
Copyright © 2011-2022 走看看