用Go构建高性能数据库中间件
Go in M
14年引入Go,最初是解决日志收集问题,后来开发了大秒,后来延伸到各个层面
Gaea简介
Gaea是数据库中间件
曾内部mycat黑盒的使用,不能及时定位问题,连接超时,Load过高,内存溢出,手工书写多种配置,易出错,难管理,历史包袱中,有多个代理,缺乏平台型方案
Gaea特点
- 分库分表,兼容mycat,kingshard路由方案
- Preoared Statements(分库分表)
- 读写分离,多个从实例负载均衡
- 多租户,租户之间软隔离
- 错误,慢sql指纹
- 配置热加载
- 连接池
- 使用TiDB sqlparser
Gaea架构
[外链图片转存失败(img-Aqw9fgVr-1562935068111)(media/15629272603061/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%202019-07-12%20%E4%B8%8B%E5%8D%887.19.32.png)]
成果
18年11月份上线,2套集群,16个非分片业务,2个分片业务
使用Gaea后QPS提升25%,并发优秀,不再被短链接打爆
服务平台化,业务申请=>DBA分配=>租户生效
prometheus+grafana监控
Why GO
并发友好:one connection per goroutine
开发效率高
工具丰富
Kingshard,vitess,tidb等优秀项目
Gaea有关的几个技术点
1.配置热加载
不用重启服务就可以让配置生效-动态分离-设计了两种方案
方案一
加载/reload,获取配置
方案二-滚动数组
提前准备好,随后将准备好的配置进行commit
会出现资源抽象问题
资源抽象
close 直接关闭
delay close 延迟关闭,将资源处理后再进行关闭
2.连接池
- 在[cap,max]范围内做到容量的自动调整
- 获取的链接一定是活跃的-采用了主动关闭+Retry
- 具备一定的超时获取机制
context是什么?
一系列实现Context接口的非导出struct
存储parent context和children context
通过afterfunc和goroutine执行超时动作
valuectx只有parent context,所以自顶向下传值
3.会话管理
服务端管理请求来的会话,通过setreaddeadline和setwritedeadline来实现
存在一些问题:
分散设置;每一次读,写都需要设置,高频操作;很消耗CPU;线上海量连接带来性能问题
解决方案1-定时设置
该方法可以解决一定问题,但仍存在一些毛病;
优势:可以缓解性能问题
缺点:有一定误差,写法繁琐;分散管理
解决方案2-时间片轮转
集中式管理;CPU消耗极低
4.GC? 内存 问题
增长到20GB就不再增长,怀疑是否出现溢出
回顾流程,猜测原因
作出优化
优化后只会增长到3GB而不是20GB,且相对稳定。
Tests
单元测试
集成测试