trove_Trove宝藏世界

trove_Trove宝藏世界一:简介一、背景1.对于公有云计算平台来说,只有计算、网络与存储这三大服务往往是不太够的,在目前互联网应用百花齐放的背景下,几乎所有应用都使用到数据库,而数据库承载的往往是应用最核心的数据

一:简介

    一、背景

       1. 对于公有云计算平台来说,只有计算、网络与存储这三大服务往往是不太够的,在目前互联网应用百花齐放的背景下,几乎所有应用都使用到数据库,而数据库承载的往往是应用最核心的数据。此外,在大数据分析越来越盛行的背景下,对数据库的可靠便捷管理也变得更为重要。因此,DBase as a Service(DBaaS,数据库服务)也就顺理成章地成为了云计算平台为用户创造价值的一个重要服务。

       2. 对比Amazon AWS中各种关于数据的服务,其中最著名的是RDS(SQL-base)和DynamoDB(NoSQL),除了实现了基本的数据管理能力,还具备良好的伸缩能力、容灾能力和不同规格的性能表现。因此,对于最炙手可热的开源云计算平台Openstack来说,也从Icehouse版加入了DBaaS服务,代号Trove。直到去年底发布的Openstack Liberty版本,Trove已经经过了4个版本的迭代发布,目前已经成为Openstack官方可选的核心服务之一。本文将深入介绍Trove的原理、架构与功能,并通过实践来展示Trove的应用。

    二、设计目标

       1. Trove is Database as a Service for OpenStack. It’s designed to run entirely on OpenStack, with the goal of allowing users to quickly and easily utilize the features of a relational or non-relational database without the burden of handling complex administrative tasks. ”这是Trove在官方首页上对这个项目的说明,有两个关键点。一个是从产品设计上说,它定位不仅仅是关系型数据库,而且还涵盖非关系数据库的服务。另一个是从产品实现上说,它是完全基于Openstack的。

       2. 从第一点可以看出Trove解决问题的高度已经超越了同类产品。因为我们从其他云计算平台对比去看,关系型和非关系型数据库都是由不同的服务去提供(比如AWS的RDS和DynamoDB),而且实现上也往往互相独立的系统,不仅UI不同,API也不一样。而Trove的目标是抽象尽可能多的东西,对外提供统一的UI和API,尽量减少冗余实现,提升平台内聚。只要具备了实例、数据库、用户、配置、备份、集群、主从复制这些概念,不管是关系型还是非关系型数据库,都能统一管理起来。从最新的Liberty版本发布的情况下,目前开源的主流关系型和非关系型数据库也得到了支持,比如Mysql(包括Percona和MariaDB分支)、Postgresql、Redis、MongoDB、CouchDB、Cassandra等等。不过根据官方的介绍,目前只有Mysql是得到了充分的生产性测试,其他的还处于实验性阶段。

       3. 而第二点完全基于Openstack的,可以说是一个较大的创新。试想,假设你是一个云计算服务商,如果现在要提供数据库服务,只需要在原有平台软件上升级与配置一下就行,其他什么都不需要,不需要采购数据库服务器硬件,不需要规划网络,不需要规划IDC,这是一种什么样的感觉?Trove完全构建于Openstack原有的几大基础服务之上。打个比喻类似于Google著名的Bigtable服务是构建于GFS、Borg、Chubby等几个基础服务之上。所以,Trove实际上拥有了云平台的一些基础特性,比如容灾隔离、动态调度、快速响应等能力,而且从研发的角度看,也大大减少了重复造轮子的现象。

 

    三、基本概念

       1. 数据库实例(Instance):包含数据库程序的openstack虚拟机,如果用户创建了一个数据库实例,那么他其实就创建了一台openstack虚拟机,并在该虚拟机上启动了数据库服务。

       2. Datastore:用来表示和存储数据库的类型、版本、虚拟机镜像等信息。当用户创建一个数据库实例时需要指定Datastore.

       3. 配置组(Configuration Group):数据库参数组成的集合。用户可以将配置组应用到一个或多个数据库实例上,因而避免了大量的重复操作。

 

    四、特点

       1. “按需”获得数据库服务器,配置所获得的数据库服务器或者数据库服务器集群

       2. 自动化操作,自动的增、删、改、备。

       3. 更好的资源利用,你可以根据业务量,自由的对数据库实例进行伸缩。

 

二:架构

    一、核心架构

            

 

    二、组件详解
        

       1. trove-api:用于操作请求的接收和分发操作提供 REST 风格的 API,同时与 trove-conductor 和 trove-taskmanager 通信,一些轻量级的请求,比如获取实例状态,实例数量等操作都是自身直接处理或访问 trove。trove-conductor 和 trove-taskmanager处理比较重量级的操作。比如创建数据库,创建备份等操作都是通过rpc传递给 trove-taskmanager,然后通过调用 nova、swift、neutron、cinder等组件来完成操作。

       2. trove-conductor:将 vm 内 trove-guestagent 发送的状态信息保存到数据库,与 trove-guestagent 的通信是通过rpc来实现的,trove-conductor 这个组件的目的是为了避免创建的数据库的实例直接访问数据库,它是做为一个 trove-guestagent 将昨天写入数据库的中间件。

       3. trove-taskmanager:执行 trove 中大部分复杂的操作,请求者发送消息到 trove-taskmanager,trove-taskmanager 在请求者的上下文中调用相应的程序执行这些请求。taskmanager 处理一些操作,包括实例的创建、删除,与其他服务如Nova、Cinder、Swift等的交互,一些更复杂的Trove操作如复制和集群,以及对实例的整个生命周期的管理。trov-taskmanager就像是其他openstak服务的客户端,如nova,swift,cinder等,当要创建数据库实例时就将请求发送给nova,让nova去创建个实例,要备份的话就调用swift接口上传备份。

       4. trove-guestagent:集成在vm镜像里面,通过监听rpc里面task manager发过来的指令,并在本地执行代码完成数据库任务,taskmanager将消息发送到guest agent,guest agent通过调用相应的程序执行这些请求。

 

   三、功能

      

       1. 动态resize能力:分为instance-resize和volume-resize,前者主要是实例运行的内存大小和cpu核数,后者主要是指数据库分区对应的硬盘卷的大小。由于实例是跑在vm上的,而vm的cpu和memory的规格可以通过Nova来进行动态调整,所以调整是非常方便快捷的。另外硬盘卷也是由Cinder提供的动态扩展功能来实现resize。resize过程中服务会有短暂的中断,是由于mysqld重启导致的。

       2. 全量与增量备份:目前mysql的实现中,备份是由实例vm上的guestagent运行xtrabackup工具进行备份,且备份后的文件会存储在Swift对象存储中。从备份创建实例的过程则相反。由于xtrabackup强大的备份功能,所以Trove要做的只是做一些粘胶水的工作。

       3. 动态配置更新:目前支持实例的自定义配置,可以创建配置组应该到一组实例上,且动态attach到运行中的实例中生效。

       4. 一主多从的一键创建:在创建数据库实例的API中,支持批量创建多个从实例,并以指定的实例做主进行同步复制。这样就方便了从一个已有实例创建多个从实例的操作。而且mysql5.6版本之后的同步复制支持GTID二进制日志,使得主从实例之间关系的建立更加可靠和灵活,在failover处理上也更加快速。

       5. 集群创建与管理(percona/mariadb支持):Cluster 功能目前在 mysql原生版本暂时不支持,但是其两个分支版本 percona和 mariadb基于 Galera库实现的集群复制技术是支持的。另外Liberty版本的Trove也提供了对mongodb的集群支持。

 

三:常用操作

    一、实例、数据库、数据库用户管理

         

 

    二、备份和集群管理

           

创建数据库实例  

 

trove_Trove宝藏世界

 

创建数据库实例时,实际上就是通过trove-taskmanager create_instance()方法去调用nova-api,然后调用 _get_injected_files方法将guet_infotrove-guetagent.conf信息注入到 数据库实例/etc/trove/conf.d/里面,提供给guest-agent进行后续的操作。

 

trove_Trove宝藏世界

所以4.0版本的trove并不需要一开始就将trove-guestagent.conf这个配置文件封装在镜像里面,这个配置文件是通过nova注入的,所以镜像只需要配置好guest-agent从哪里读这个配置文件。剩下的就交给trove-guestagent guest_info_file这个配置文件。

[root@w-test01 conf.d]# cat guest_info.conf 

[DEFAULT]

guest_id=7ec35639-5139-4ae4-8388-8101e41cc0f7 #这个ID是trove 分配给这个实例的ID

datastore_manager=mysql             #采用的是哪个datastore

tenant_id=f2f0e038ff0342a3bc99d8971f829ac2 #是哪个租户的

 

当你在控制台输入需要创建的云硬盘的大小时,实际上是通过调用taskmanager里面的_create_volume方法:

 

trove_Trove宝藏世界

收集齐上面那些信息后,然后调用nova来创建数据库实例:

trove_Trove宝藏世界

然后数据库实例里面的guest-agent会去读取通过nova注入的trove-guestagent.conf 去连接rpc读取taskmanager发送过来的操作请求。

剩下的一些操作比如创建数据库、创建用户这些都是taskmanager调用数据库实例里面的guest-agent去实现。

guest-agent对mysql的一些操作实现是在/usr/lib/python2.7/dist-packages/trove/guestagent/datastore/mysql/service_base.py 他里面包含了

def _get_actual_db_status() #获取数据库实例状态方法

 

主要是通过调用/usr/bin/mysqladmin ping” 和ps -C mysqld h 去获取数据库实例状态。

trove_Trove宝藏世界

通过判断pid文件是否存在来判断mysql是否shutdown:

 

trove_Trove宝藏世界

 

def create_database #创建数据库实例方法:

trove_Trove宝藏世界

 

def create_user #创建用户并且授权方法:

 

trove_Trove宝藏世界

 

后面还有删除数据库,删除用户,获取binlog,开始slave、关闭slave等方法。

同时需要注意的是trove创建数据库实例时,会默认为每个数据库实例同时创建一个。

trove_Trove宝藏世界

SecGroup-xxx xxx为主机ID的安全组。

trove默认是不启动root用户的所以在控制台用户选项卡里面用户名称是不能填root的。

需要注意的是上述所有操作都是由trove用户来执行,所以必须要确认的是trove用户拥有sudo权限,否则会失败。

在执行完上述操作前此时数据库状态还是building状态的, 那就是 vm 正在启动,创建数据库,创建用户,对用户授权,同步my.cnf配置文件到数据库实例内,重启mysql ,trove-guestagent 发送 rpc 。

给trove-taskmanager,最后检测数据库成功运行后发送 Active 状态消息给 rpc,trove-taskmanager 收到 Active 消息后,不再发送创建数据库消息,而 trove-conductor 同时收到 trove-guestagent Active 消息后,去数据库里更新 trove instance 的状态,在trove list 就可以看见instance Active 的状态了。

备份还原  

 

trove_Trove宝藏世界

 

目前trove-guestagent只支持mysql的三种备份方式,一种是传统的mysql Dump方式一种是InnoBackupEx 还有增是InnoBackup的增量备份方式InnoBackupExIncremental。

备份的程序放在/usr/lib/python2.7/dist-packages/trove/guestagent/strategies/backup。

其调用方式也比较简单,就是trove-guestagent.conf里面配置了什么备份方式就调用指定类执行里面的方法,方法内也都是一些软件的命令。

 

trove_Trove宝藏世界

trove_Trove宝藏世界

trove_Trove宝藏世界

需要注意的是默认不配置是调用Innobackup,备份的日志会存在tmp目录下,备份完成后默认是会存储到swift内。

 

trove_Trove宝藏世界

默认备份在swift内的备份文件夹为database_backups 、开启压缩、ssl加密,分片等。

调用SwiftStorage类里面的save方法上传到Swift中

trove_Trove宝藏世界

trove_Trove宝藏世界

其中会进行文件的校验。

是备份上去的实际上有两个文件,第一个enc文件主要是用来分片使用,第二个文件才是主要的备份文件。

trove_Trove宝藏世界

mysql主从  

 

trove_Trove宝藏世界

 

trove-master端先将当前数据备份到Swift—>然后taskmanager重新创建个数据库实例——>新创建的数据库实例将刚刚的备份从Swift拉下来根据里面的bin-log里面的GTID进行还原—->建立主从关系—检测创建成功taskmanager删除上传到Swift的备份。

备份前会做个检测,发现以前有备份就调用增量备份的方法节省空间,检测到没有就调用全备的方法。

这里先做个变量定义,定义好增量备份和全备的变量:

trove_Trove宝藏世界

if判断调用全备还是增量备份。

 

trove_Trove宝藏世界

 

目前trove只支持mysql的主从不支持主主并且还是异步的主从。

创建主从时,创建从同样是调用create_instance()方法:

 

trove_Trove宝藏世界

 

只是这里做了个判断,如果传过来了slave_of_id就调用__create_replication_slave()方法:

 

trove_Trove宝藏世界

__create_replication_slave()方法会去获去备份的ID ,然后继续调用nova创建主机。

接下来操作会交给数据库实例里面的guest-agent进行操作。

guest-agent会先将备份文件从来Swift 下载下来。然后还原。接下来建立主从关系,这里要说明的是trove建立主从关系的方式有两种一种是传统的bin-log的形式,一种的用GTID的形式。

在 /usr/lib/python2.7/dist-packages/trove/common/cfg.py

这个是定义的两个不同的策略:

 

trove_Trove宝藏世界

同时也会调用不同的方法去执行。

当你的配置文件

replication_strategy = MysqlBinlogReplication

replication_namespace = trove.guestagent.strategies.replication.mysql_binlog

调用的是

/usr/lib/python2.7/dist-packages/trove/guestagent/strategies/replication/mysql_binlog.py

replication_strategy = MysqlGTIDReplication

replication_namespace = trove.guestagent.strategies.replication.mysql_gtid

调用的是

/usr/lib/python2.7/dist-packages/trove/guestagent/strategies/replication/mysql_gtid.py

这两个文件有何不同,方法内定义的命令不同:

 

trove_Trove宝藏世界

trove_Trove宝藏世界

GTID的概述:

全局事物标识:global transaction identifieds。

GTID事物是全局唯一性的,且一个事务对应一个GTID。一个GTID在一个服务器上只执行一次,避免重复执行导致数据混乱或者主从不一致。GTID用来代替classic的复制方法,不在使用binlog+pos开启复制。而是使用master_auto_postion=1的方式自动匹配GTID断点进行复制。MySQL-5.6.5开始支持的,MySQL-5.6.10后开始完善。在传统的slave端,binlog是不用开启的,但是在GTID中,slave端的binlog是必须开启的,目的是记录执行过的GTID(强制)。

下面介绍一下mysql GTID:

GTID的组成部分:

前面是server_uuid:后面是一个序列号

例如:server_uuid:sequence number

7800a22c-95ae-11e4-983d-080027de205a:10

UUID:每个mysql实例的唯一ID,由于会传递到slave,所以也可以理解为源ID。

Sequence number:在每台MySQL服务器上都是从1开始自增长的序列,一个数值对应一个事务。

GTID比传统复制的优势:

  • 更简单的实现failover,不用以前那样在需要找log_file和log_Pos。

  • 更简单的搭建主从复制。

  • 比传统复制更加安全。

GTID是连续没有空洞的,因此主从库出现数据冲突时,可以用添加空事物的方式进行跳过。

GTID的工作原理:

master更新数据时,会在事务前产生GTID,一同记录到binlog日志中。slave端的i/o 线程将变更的binlog,写入到本地的relay log中。sql线程从relay log中获取GTID,然后对比slave端的binlog是否有记录。如果有记录,说明该GTID的事务已经执行,slave会忽略。如果没有记录,slave就会从relay log中执行该GTID的事务,并记录到binlog。在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。

要点:

  1. slave在接受master的binlog时,会校验master的GTID是否已经执行过(一个服务器只能执行一次)。

  2. 为了保证主从数据的一致性,多线程只能同时执行一个GTID。

今天的文章trove_Trove宝藏世界分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/77169.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注