学习RadonDB源码(二)
1. 为我新的一天没有放弃而喝彩
学习是一件很容易放弃的事情,因为就算是不学,我也能在现在的岗位上发光发热。可是人不就是一个热爱折腾的种群吗?
今天没有放弃不代表明天没有放弃,也许放弃的可能性大于坚持的可能性,不管怎样,坚持一天算一天。
RadonDB面对着TiDB,OceanBase等等数据库的竞争,都是分布式数据库,为什么要首先学习RadonDB呢?毕竟这是一款真的基于MySQL而不是兼容MySQL的产品,通过学习RadonDB,也许有一天我能在其源码上做出点什么贡献也未可知,我起码对MySQL的熟悉程度更高。
2. 继续昨天的话题
昨天我写到了程序的主入口,注意其最重要的一句:
// Proxy.
proxy := proxy.NewProxy(log, flagConf, build.Tag, conf)
proxy.Start()
一切都是从这里开始的,为什么这么说呢?
这一启动,就好像启动了一个mysqld一样,可以正常的接收mysql客户端的连接请求。
根据昨天讲述的,proxy的启动实际上是执行了Accept方法,而Accept则是以服务形式启动起来,并且监听了几个端口的。
那我们再来看看Accept方法:
// Accept runs an accept loop until the listener is closed.
func (l *Listener) Accept() {
runtime.GOMAXPROCS(runtime.NumCPU())
for {
conn, err := l.listener.Accept()
if err != nil {
// Close() was probably called.
return
}
ID := l.connectionID
l.connectionID++
go l.handle(conn, ID, l.serverVersion)
}
}
从代码逻辑上看,只要没有执行Close,就会一直循环监听下去,监听的就是一个一个的网络连接请求。
我猜测这里的连接就好像是我们在MySQL中执行“show processlist”的时候,显示的信息,每来一个连接,就会给它分配一个ID,并启动一个监听器的handler goroutine,可以理解为启动了一个线程,这个线程专门负责该连接。
到这里我们就可以肯定,RadonDB也是一个单进程多线程的架构,和MySQL并无二致。
现在就可以分析分析handler方法到底做了什么。这个方法很长很长,我实在是不能一行一行的粘贴过来,只是捡一些有代表性的讲讲。
// handle is called in a go routine for each client connection.
func (l *Listener) handle(conn net.Conn, ID uint32, serverVersion string) {}
首先映入眼帘的一定是注释,良好的代码一定拥有良好的注释。注释告诉我们,这个handler方法是处理每个客户端连接的。
客户端连接嘛,每个DBA都知道,连接上来就是为了执行SQL的命令的,有一般的DDL,DML还有些指令性命令。
那么我推断代码里一定有一个switch分支用于对每种命令进行处理:
for {
if data, err = session.packets.Next(); err != nil {
return
}
// Update the session last query time for session idle.
session.updateLastQueryTime(time.Now())
switch data[0] {
// COM_QUIT
case sqldb.COM_QUIT:
return
// COM_INIT_DB
case sqldb.COM_INIT_DB:
db := l.parserComInitDB(data)
if err = l.handler.ComInitDB(session, db); err != nil {
if werr := session.writeErrFromError(err); werr != nil {
return
}
} else {
session.SetSchema(db)
if err = session.packets.WriteOK(0, 0, session.greeting.Status(), 0); err != nil {
return
}
}
// COM_PING
case sqldb.COM_PING:
if err = session.packets.WriteOK(0, 0, session.greeting.Status(), 0); err != nil {
return
}
// COM_QUERY
case sqldb.COM_QUERY:
query := l.parserComQuery(data)
if err = l.handler.ComQuery(session, query, nil, func(qr *sqltypes.Result) error {
return session.writeTextRows(qr)
}); err != nil {
log.Error("server.handle.query.from.session[%v].error:%+v.query[%s]", ID, err, query)
if werr := session.writeErrFromError(err); werr != nil {
return
}
}
//省略其他
还真的是有,逻辑也不复杂,其实刚才的代码里没有展现出session的概念,先讲讲session在回过头来讲刚才的代码:
session := newSession(log, ID, l.serverVersion, conn)
//省略一些session的检查等操作
l.handler.SessionInc(session)
defer l.handler.SessionDec(session)
// Reset packet sequence ID.
session.packets.ResetSeq()
核心思想就是新建了一个session,之后,才有了刚才的操作,要从session中拿出用户操作来,放在一个叫做data的切片中,然后判断切片中具体的操作类型。
到这里应该很多人都会知道,RadonDB到底做了一个什么样的入口了,其实就是做了一个自己的MySQL服务,监听特定的端口,接收用户的操作。
这里所有的代码都可以参考以下这个github项目:
作者也是RadonDB的作者之一。这个go-mysqlstack的目的也很简单,就是实现一个mysqld:
官方给的示例,就是启动了一个服务端:
对于交付的客户来说,其实就是在用MySQL,只不过端口有变,服务的启动方式和配置方式不太一样,但是写代码还是用jdbc-driver,对于开发者来说没有任何变化。
3. 小结
Go语言真有意思,利用已经成熟的项目来学习Go语言,我觉得比一点一点看书来的快一些。
当然了,学会了写之后就要思考,思考这门语言,真的做到Thinking in Go。
真是学而不思则罔。
学习RadonDB源码(二)的更多相关文章
- 学习RadonDB源码(一)
1. 可能是开始也可能是结束 RadonDB是国内知名云服务提供商青云开源的一款产品,下面是一段来自官方的介绍: QingCloud RadonDB 是基于 MySQL 研发的新一代分布式关系型数据库 ...
- 学习RadonDB源码(三)
1. 所谓第四代语言 SQL是一种典型的第四代语言,即4GL,这种语言的突出特点是编写者不需要关注怎么做,只需要告诉系统我要什么就可以. 虽然4GL是这样的一种语言,大大简化了编写者的编写难度,其实底 ...
- 手牵手,从零学习Vue源码 系列二(变化侦测篇)
系列文章: 手牵手,从零学习Vue源码 系列一(前言-目录篇) 手牵手,从零学习Vue源码 系列二(变化侦测篇) 陆续更新中... 预计八月中旬更新完毕. 1 概述 Vue最大的特点之一就是数据驱动视 ...
- Jetty源码学习-编译Jetty源码二三事
工作小几个月了,JDK基础和web应用框架学的的差不多了,开始学习Jetty源码,费了小半天才编译成功,把自己拆过的坑记录下来. 编译前的环境: MAVEN 3.3.Eclips eLuna Serv ...
- 一起学习vue源码 - Object的变化侦测
作者:小土豆biubiubiu 博客园:www.cnblogs.com/HouJiao/ 掘金:https://juejin.im/user/58c61b4361ff4b005d9e894d 简书:h ...
- 手牵手,从零学习Vue源码 系列一(前言-目录篇)
系列文章: 手牵手,从零学习Vue源码 系列一(前言-目录篇) 手牵手,从零学习Vue源码 系列二(变化侦测篇) 手牵手,从零学习Vue源码 系列三(虚拟DOM篇) 陆续更新中... 预计八月中旬更新 ...
- 学习JUC源码(2)——自定义同步组件
前言 在之前的博文(学习JUC源码(1)--AQS同步队列(源码分析结合图文理解))中,已经介绍了AQS同步队列的相关原理与概念,这里为了再加深理解ReentranLock等源码,模仿构造同步组件的基 ...
- 学习JUC源码(1)——AQS同步队列(源码分析结合图文理解)
前言 最近结合书籍<Java并发编程艺术>一直在看AQS的源码,发现AQS核心就是:利用内置的FIFO双向队列结构来实现线程排队获取int变量的同步状态,以此奠定了很多并发包中大部分实现基 ...
- 学习JUC源码(3)——Condition等待队列(源码分析结合图文理解)
前言 在Java多线程中的wait/notify通信模式结尾就已经介绍过,Java线程之间有两种种等待/通知模式,在那篇博文中是利用Object监视器的方法(wait(),notify().notif ...
随机推荐
- ipython notebook 如何打开.ipynb文件?
标签: pythontensorflow 2017-03-29 14:17 235人阅读 评论(0) 收藏 举报 分类: TensorFlow(13) 转自:https://www.zhihu.c ...
- centos 6 7 differences 区别
命令 centos6 centos7 ifconfig 有 有 yum install -y net-tools 服务管理 chkconfig /etc/init.d/服务 systemctl sys ...
- beyond compare添加右键快捷方式
如果安装beyond compare后,右键不能出现比较选项,可以通过设置 beyond compare完成. 选择 工具->选项,在资源管理器整合下面,有一个在资源管理器关联菜单中显示beyo ...
- Java面向对象编程(一)
由于常常将Java和C++面向对象编程的原则搞乱,所以这次把相关要点分别总结一下,本文主要总结Java面向对象编程. 面向对象编程的三大特性是:继承性(inheritance), 多态性(polymo ...
- EasyDarwin实现RTSP播放动态认证的两种方式:Basic/Digest & Token
问题描述 目前为了能够方便开发者,我们将EasyDarwin中的RTSP认证过程直接忽略过了,如果要开启认证的方式,我们可以在代码中打开: case kRoutingRequest: { // Inv ...
- openjdk源码目录结构
1 openjdk源码 http://hg.openjdk.java.net 选择jdk8u这个project, 然后选择jdk8u20这个repository. 2 目录结构 corba: comm ...
- (转)基于RTP的H264视频数据打包解包类
最近考虑使用RTP替换原有的高清视频传输协议,遂上网查找有关H264视频RTP打包.解包的文档和代码.功夫不负有心人,找到不少有价值的文档和代码.参考这些资料,写了H264 RTP打包类.解包类,实现 ...
- Impala 安装笔记1一Cloudera CDH4.3.0安装
Impala是Cloudera在受到Google的Dremel启发下开发的实时交互SQL大数据查询工具,Impala没有再使用缓慢的Hive+MapReduce批处理,而是通过使用与商用并行关系数据库 ...
- 火狐浏览器使用firebug获取xpath和css path
工作中,常常会用到网页元素的定位方式,常用的有xpath和css path两种定位方式. 现在简单介绍如何使用工具自动生成元素的定位字符串. 首先介绍在火狐浏览器上使用FireBug及其扩展FireP ...
- runtime之方法的交换
工作中没怎么用到runtime的东西,所以一直没怎么看,现在开始拿起来. runtime之方法的交换: 都知道OC中有category可以对已知类进行扩展,但是假如工程中需要修改某类的原方法,若用ca ...