Golang进阶,揉碎数据库中间件,干货满满!(二)

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: Golang进阶,揉碎数据库中间件,干货满满!(二)

七、权限管理实现原理#


重点关注的地方:


# 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

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
SQL 关系型数据库 MySQL
探索Gorm - Golang流行的数据库ORM框架
探索Gorm - Golang流行的数据库ORM框架
|
19天前
|
缓存 负载均衡 监控
探秘数据库中间件:ProxySQL与MaxScale的优势与劣势
探秘数据库中间件:ProxySQL与MaxScale的优势与劣势
14 2
|
18天前
|
缓存 NoSQL 中间件
应对数据库不断膨胀的数据:缓存和队列中间件
【6月更文挑战第5天】该文探讨了优化数据库使用以提升应用系统性能的策略。文中建议利用Redis缓存和MQ消息队列作为辅助工具,以进一步优化性能和减少资源消耗。
19 2
应对数据库不断膨胀的数据:缓存和队列中间件
|
11天前
|
SQL 关系型数据库 MySQL
mysqldiff - Golang 针对 MySQL 数据库表结构的差异 SQL 工具
Golang 针对 MySQL 数据库表结构的差异 SQL 工具。https://github.com/camry/mysqldiff
46 7
|
1月前
|
缓存 监控 中间件
中间件Cache-Aside策略应用程序直接与缓存和数据库进行交互
【5月更文挑战第8天】中间件Cache-Aside策略应用程序直接与缓存和数据库进行交互
35 4
|
1月前
|
SQL 关系型数据库 MySQL
Golang数据库编程详解 | 深入浅出Go语言原生数据库编程
Golang数据库编程详解 | 深入浅出Go语言原生数据库编程
|
1月前
|
JavaScript 前端开发 中间件
Node.js—Express使用、Express 路由 、Express 中间件、托管静态资源、使用 Express 写接口、node.js链接sqlite数据库
Node.js—Express使用、Express 路由 、Express 中间件、托管静态资源、使用 Express 写接口、node.js链接sqlite数据库
150 0
|
1月前
|
算法 NoSQL Java
2023年阿里高频Java面试题:分布式+中间件+高并发+算法+数据库
又到了一年一度的金九银十,互联网行业竞争是一年比一年严峻,作为工程师的我们唯有不停地学习,不断的提升自己才能保证自己的核心竞争力从而拿到更好的薪水,进入心仪的企业(阿里、字节、美团、腾讯.....)
|
7月前
|
中间件 Java 应用服务中间件
重磅!基础+Spring+并发+调优+微服务+数据库+中间件已肝完
在金三银四时也参与过不少面试,2021都说工作不好找,也是对开发人员的要求变高。前段时间自己有整理了一些Java后端开发面试常问的高频考点问题做成一份PDF文档(1000道高频题),同时也整理一些图文解析及笔记,今天在这免费分享给大家,希望大家在即将的十月面试做好复习,长期的积累和短期的突击让自己能找到一个满意的工作!
|
7月前
|
Go 数据库
Golang面向对象小案例(未连接数据库)
Golang面向对象小案例(未连接数据库)
25 0