当前位置: 首页 > 科技观察

如果你被要求设计数据库中间件

时间:2023-03-22 01:09:46 科技观察

负责2013年底数据库中间件设计的设计文档,分享给大家:你懂的数据库中间件技术,你懂的架构师的系统设计思路1.整体目标数据库中间层项目后台不再开发。根据之前和公司同事的研究和讨论,中间层有两个核心目标:db虚拟化:让db对业务线透明(本文中的db指的是mysql),业务线是no不再需要知道db的真实ip、端口、主从关系、读写关系、高可用分库支持:让db的分库对业务线透明2.实现的功能上面的目标比较宽泛,具体来说,数据库中间层需要实现以下功能。(1)统一访问入口如果统一访问入口,以后就没有db1.58.com:3306db2.58.com:3306im.58.com:3306jiaoyou.58.com:3306只有db.58.com:3306所有业务线只有一次访问db,数据库中间层做授权校验,中间件路由请求。这是绝对的情况。当然,统一一个总入口的目标有点宏大,还是可以循序渐进的。首先,所有业务线统一读写访问入口,所以折衷的目标可以是以后不再有im.read.db1.58.com:3306im.read.db2.58.com:3306im.write.db.58.com:3306和im.58.com:3306im业务访问db统一到一个入口,中间层智能路由请求。更简化一点,即使是前期同一业务线的db读写,对业务线也不透明,数据库中间层只做简单的请求转发,初步收集数据库访问入口到中间层数据库,为后续统一,再统一基础。ROAD-MAP方案如下:统一业务线入口(转账请求)统一业务线入口(智能路由)统一全局入口(2)保持访问接口原有的db访问方式,主要有以上三种方式:手动使用mysql客户端连接mysql,直接连接数据库执行命令java使用jdbc连接数据库c/c++使用libmysqlclient。由于SQL协议非常复杂,db的client和server插入一个中间层后,不一定能支持所有的SQL功能,支持哪些SQL需要慎重考虑。(3)屏蔽读写分离业务层无需关注读写分离,由中间件进行读写请求路由。(4)支持的分库58的db的水平扩展基本都是采用分库的方式(分库比较好,方便扩展实例),即:db.table会被水平拆分成:db1.tabledb2.tabledb3.tabledb4.table的话,dao层对于表只有一个表实例,比较方便。根据前期与各业务线同学的沟通,58对分库的业务接入需求如下(调研周期较长,与多个业务线沟通):patitionkeygeneralqueryINqueryonpatitionkeynon-patitionkey上面的查询只有排序+分页查询的功能有限,所以对于分库上的分布式SQL功能,数据库中间层只需要支持以上四项即可。(5)高可用支持高可用支持分为两部分:***部分,故障自动检测:当下游数据库宕机时,能自动发现问题,并通知相关人员。第二部分,自动故障转移:当主库宕机时,可以自动切换,或者写请求阻塞,如果从库宕机,可以自动切换读请求流中间件宕机,自动切换中间件流量,高可用(6)可操作性的支持,支持一些统计数据的展示,支持一些管理命令的运维,支持页面的运维。但是,只要整体框架设计具有可扩展性,这些功能是可以逐步添加的。3、设计折衷(1)协议及总体架构由于选择mysqlclient-server协议作为业务层和中间层之间的协议,中间层必须作为mysql-server接收上游请求,并向真实服务器发送请求作为mysql客户端。mysql发送请求时,中间层的整体结构如下:这种情况下,需要对mysql客户端服务器协议做详细的研究,了解:连接建立过程,权限认证过程,压缩还有解压过程,请求响应二进制协议,各种细节...协议这部分的掌握一定要详细。好在官方文档比较全面:http://dev.mysql.com/doc/internals/en/client-server-protocol.html(2)架构细节整体架构细节如上所示。(2.1)上游mysql客户端,java使用jdbc作为上游连接,c/c++使用libmysql.a作为上游连接,使用MysqlClientServer协议DBA也可以向中间件发送一些管理命令,或者查看一些统计信息,它使用自己定义的内部协议(2.2)。下游位于系统架构的顶端。系统中间件的下游是mysql集群,中间件和mysql之间也使用了MysqlClientServer协议。(2.3)中间层——ConfigMgr中间层配置文件管理组件ConfigMgr是中间层非常重要的一个部分。请求转发、读写分离、支持分库功能都需要通过配置来完成。从配置文件可以看出ConfigMgr需要管理的mysql的配置有两种类型:type=1请求转发配置的意思是如果上游访问逻辑数据库logic_db="im",中间件将请求转发给实际的后端数据库item,item配置了后台数据库的ip/port/nametype=2分库支持在说明配置分库支持之前,先说明一下数据库LOGIC_DB、PARTITION、ITEM的层次结构。LOGIC_DB:逻辑数据库,面向上游,如umcPARTITION:数据库分区,可以理解为分库,如umc0、umc1,对上游透明。ITEM:databaseitem,可以理解为一个分区上的读库或者写库,这个对上游也是透明的。上例对应的配置文件为:LOGIC_DB:需要关注partition-key-column,还需要关注分区算法,需要实现对PARTITION的请求路由和结果集的汇总PARTITION:需要注意ITEM的读写特性,需要实现ITEM的读写分离ITEM:是最终的数据库,其相关配置为数据库ip/port/name/wr-type(2.4)中间层-MysqlServerPart中间层服务器组件MysqlServerPart是中间层一个很重要的部分,它负责ble用于端口监听+请求接收和返回(服务器服务器端网络IO)、MysqlProtocol解析MysqlServerPart组件根据其功能主要分为两个组件:ServerIOMgr组件(服务器端IO管理)和MysqlProtocolAnalyzer组件(Mysql协议解析)。这一层面临这些细节:服务器网络框架的选择:建议使用异步服务器并发模型的选择:建议使用IO线程+多工作线程并发模型内存管理模型的选择:建议使用使用内存池连接上下文管理,最容易想到的上下文,一个数据库连接就是Mysql绑定到一个逻辑库LOGIC_DB如何建立数据库连接:需要考察Mysql协议Mysql协议详解:需要考察Mysqlprotocol...(2.5)Middlelayer-MysqlClientPart中间层客户端端组件MysqlClientPart是中间层非常重要的一个部分,负责中间件对mysql的连接池管理和返回结果集的解析.MysqlClientPart组件根据其功能主要分为ClientConnPoolMgr组件(客户端连接池管理)、ResultSetAnalyzer组件(返回结果集分析)两个组件。这一层面临这些细节:数据库连接池的实现数据库连接模型的选择:建议前期使用同步模型连接上下文管理。最容易想到的上下文,一个数据库连接就是对一个ITEM绑定的Mysql结果集的细化分析:需要考察Mysql协议...(2.6)中间层-SqlParser中间层Sql分析组件SqlParser是中间层的一个非常重要的部分,负责SQL语句的语法分析和语义分析。为什么要分析Sql的语法和语义?需要解析什么?分为两种情况:type=1requestforwarding请求转发,上游的一个数据库连接对应一个逻辑库LOGIC_DB,ConfigMgr可以知道它对应下游一个真实的ITEM(ip/port/db).这时候直接转发请求就可以了,不需要解析Sql语句。type=2分库支持对于分库支持,解析Sql语句可能需要回答这些问题:Sql是否有partition-key-column?分区键列的值是多少?比如一条Sql语句:select*fromuserwhereuid=123456;必须解析出“uid”列属性和uid列属性值“123456”,用于后续的请求路由。注意:更详细的情况是对于每张表,分库的partition-key-column是不一样的。上面的例子中,还需要解析出表名user。这个级别面临这些细节:如何解析Sql语句:可以参考mysql源码对SQL语句的解析,也可以参考cober对SQL语句的解析方法;注意:由于我们只需要支持多数据库,数据库名称信息在“Connection”层,我们支持的分布式Sql类型有限,所以只需要partition-key-column,offset/limit,等需要解析。(2.7)中间层-SqlModifier中间层Sql修改组件SqlModifier是中间层非常重要的一个部分,负责重写sql语句。为什么要重写Sql语句?对于type=1的请求转发,不需要修改Sql,但是对于type=2的分库支持,需要重写部分Sql语句。例如:select*fromuserwhereuidin(1,2,3,4,5,6);假设PARTITION分为0和1校验的两个分区,则sql应该改写为:select*fromuserwhereuidin(2,4,6);=>到图书馆0的路线;选择*fromuserwhereuidin(1,3,5);=>通往图书馆1的路线;另一个例子:select*fromuserlimit1000,10;那么sql可以改写为:select*fromuserlimit0,1010;=>分别路由到两个数据库,收集结果集一共2020条记录,然后从1000-1010中排序选出10条记录。需要改写哪个Sql,怎么改写?结合我们需要实现的四种分布式Sql:patitionkeygeneralqueryINqueryonpatitionkeyqueryonpatitionkeyqueryonnon-patitionkeylimitedfunctionsorting+pagingquery只需要重写(2)和(4)两项,重写方法是文中提到,(4)的改写效率较低,慎用。(2.8)中间层-SqlRouter中间层Sql路由组件SqlRouter是中间层非常重要的一个部分,负责路由sql语句。需要路由哪个Sql以及如何路由?结合我们需要实现的四种分布式Sql:patitionkeygeneralqueryINqueryonpatitionkeyqueryonpatitionkeylimitedfunctionsorting+pagingqueryonly(1)and(2)needrouting,(3)and(4))需要将请求分发到所有PARTITION。(2.9)中间层——ResultSetMerger中间层结果集合并组件ResultSetMerger是中间层中非常重要的一个部分,负责对结果集进行合并和过滤。哪个Sql需要合并结果集和过滤结果集?结合我们需要实现的四种分布式Sql:patitionkeycommonqueryINqueryonpatitionkeyqueryonpatitionkeylimitedfunctionsorting+paginationquery其中查询类型(2)和(3)需要合并结果sets,(4)不仅要合并结果集,还要在本地对结果集进行排序,然后过滤掉真正的结果集。(2.10)其他组件AdminServer:监听新端口并接收数据库管理员命令的服务器AdminMgr:实现管理员命令的组件MonitorMgr:实现监控报警的组件StatisticsMgr:实现数据统计的组件以上组件可以逐步添加,因此,第一阶段需要实现的组件和架构图是:感谢您阅读,说明您对数据库中间件感兴趣。推荐PC端看三遍,肯定收获更大。