HIVE和HBASE区别

1. 两者分别是什么?

Apache Hive是一个构建在Hadoop基础设施之上的数据仓库。通过Hive可以使用HQL语言查询存放在HDFS上的数据。HQL是一种类SQL语言,这种语言最终被转化为Map/Reduce. 虽然Hive提供了SQL查询功能,但是Hive不能够进行交互查询–因为它只能够在Haoop上批量的执行Hadoop。

Apache HBase是一种Key/Value系统,它运行在HDFS之上。和Hive不一样,Hbase的能够在它的数据库上实时运行,而不是运行MapReduce任务。Hive被分区为表格,表格又被进一步分割为列簇。列簇必须使用schema定义,列簇将某一类型列集合起来(列不要求schema定义)。例如,“message”列簇可能包含:“to”, ”from” “date”, “subject”, 和”body”. 每一个 key/value对在Hbase中被定义为一个cell,每一个key由row-key,列簇、列和时间戳。在Hbase中,行是key/value映射的集合,这个映射通过row-key来唯一标识。Hbase利用Hadoop的基础设施,可以利用通用的设备进行水平的扩展。

2. 两者的特点

Hive帮助熟悉SQL的人运行MapReduce任务。因为它是JDBC兼容的,同时,它也能够和现存的SQL工具整合在一起。运行Hive查询会花费很长时间,因为它会默认遍历表中所有的数据。虽然有这样的缺点,一次遍历的数据量可以通过Hive的分区机制来控制。分区允许在数据集上运行过滤查询,这些数据集存储在不同的文件夹内,查询的时候只遍历指定文件夹(分区)中的数据。这种机制可以用来,例如,只处理在某一个时间范围内的文件,只要这些文件名中包括了时间格式。

HBase通过存储key/value来工作。它支持四种主要的操作:增加或者更新行,查看一个范围内的cell,获取指定的行,删除指定的行、列或者是列的版本。版本信息用来获取历史数据(每一行的历史数据可以被删除,然后通过Hbase compactions就可以释放出空间)。虽然HBase包括表格,但是schema仅仅被表格和列簇所要求,列不需要schema。Hbase的表格包括增加/计数功能。

3. 限制

Hive目前不支持更新操作。另外,由于hive在hadoop上运行批量操作,它需要花费很长的时间,通常是几分钟到几个小时才可以获取到查询的结果。Hive必须提供预先定义好的schema将文件和目录映射到列,并且Hive与ACID不兼容。

HBase查询是通过特定的语言来编写的,这种语言需要重新学习。类SQL的功能可以通过Apache Phonenix实现,但这是以必须提供schema为代价的。另外,Hbase也并不是兼容所有的ACID特性,虽然它支持某些特性。最后但不是最重要的–为了运行Hbase,Zookeeper是必须的,zookeeper是一个用来进行分布式协调的服务,这些服务包括配置服务,维护元信息和命名空间服务。

4. 应用场景

Hive适合用来对一段时间内的数据进行分析查询,例如,用来计算趋势或者网站的日志。Hive不应该用来进行实时的查询。因为它需要很长时间才可以返回结果。

Hbase非常适合用来进行大数据的实时查询。Facebook用Hbase进行消息和实时的分析。它也可以用来统计Facebook的连接数。

5. 总结

Hive和Hbase是两种基于Hadoop的不同技术–Hive是一种类SQL的引擎,并且运行MapReduce任务,Hbase是一种在Hadoop之上的NoSQL 的Key/vale数据库。当然,这两种工具是可以同时使用的。就像用Google来搜索,用FaceBook进行社交一样,Hive可以用来进行统计查询,HBase可以用来进行实时查询,数据也可以从Hive写到Hbase,设置再从Hbase写回Hive。

ZooKeeper典型应用场景一览

原文

ZooKeeper 典型应用场景一览

数据发布与订阅(配置中心)
发布与订阅模型,即所谓的配置中心,顾名思义就是发布者将数据发布到ZK节点上,供订阅者动态获取数据,实现配置信息的集中式管理和动态更新。例如全局的配置信息,服务式服务框架的服务地址列表等就非常适合使用。

应用中用到的一些配置信息放到ZK上进行集中管理。这类场景通常是这样:应用在启动的时候会主动来获取一次配置,同时,在节点上注册一个Watcher,这样一来,以后每次配置有更新的时候,都会实时通知到订阅的客户端,从来达到获取最新配置信息的目的。 分布式搜索服务中,索引的元信息和服务器集群机器的节点状态存放在ZK的一些指定节点,供各个客户端订阅使用。
分布式日志收集系统。这个系统的核心工作是收集分布在不同机器的日志。收集器通常是按照应用来分配收集任务单元,因此需要在ZK上创建一个以应用名作为path的节点P,并将这个应用的所有机器ip,以子节点的形式注册到节点P上,这样一来就能够实现机器变动的时候,能够实时通知到收集器调整任务分配。 系统中有些信息需要动态获取,并且还会存在人工手动去修改这个信息的发问。通常是暴露出接口,例如JMX接口,来获取一些运行时的信息。引入ZK之后,就不用自己实现一套方案了,只要将这些信息存放到指定的ZK节点上即可。 注意:在上面提到的应用场景中,有个默认前提是:数据量很小,但是数据更新可能会比较快的场景。

负载均衡
这里说的负载均衡是指软负载均衡。在分布式环境中,为了保证高可用性,通常同一个应用或同一个服务的提供方都会部署多份,达到对等服务。而消费者就须要在这些对等的服务器中选择一个来执行相关的业务逻辑,其中比较典型的是消息中间件中的生产者,消费者负载均衡。
消息中间件中发布者和订阅者的负载均衡,linkedin开源的KafkaMQ和阿里开源的metaq都是通过zookeeper来做到生产者、消费者的负载均衡。这里以metaq为例如讲下: 生产者负载均衡:metaq发送消息的时候,生产者在发送消息的时候必须选择一台broker上的一个分区来发送消息,因此metaq在运行过程中,会把所有broker和对应的分区信息全部注册到ZK指定节点上,默认的策略是一个依次轮询的过程,生产者在通过ZK获取分区列表之后,会按照brokerId和partition的顺序排列组织成一个有序的分区列表,发送的时候按照从头到尾循环往复的方式选择一个分区来发送消息。消费负载均衡:

在消费过程中,一个消费者会消费一个或多个分区中的消息,但是一个分区只会由一个消费者来消费。MetaQ的消费策略是:

每个分区针对同一个group只挂载一个消费者。 如果同一个group的消费者数目大于分区数目,则多出来的消费者将不参与消费。
* 如果同一个group的消费者数目小于分区数目,则有部分消费者需要额外承担消费任务。
在某个消费者故障或者重启等情况下,其他消费者会感知到这一变化(通过 zookeeper watch消费者列表),然后重新进行负载均衡,保证所有的分区都有消费者进行消费。

命名服务(Naming Service)
命名服务也是分布式系统中比较常见的一类场景。在分布式系统中,通过使用命名服务,客户端应用能够根据指定名字来获取资源或服务的地址,提供者等信息。被命名的实体通常可以是集群中的机器,提供的服务地址,远程对象等等——这些我们都可以统称他们为名字(Name)。其中较为常见的就是一些分布式服务框架中的服务地址列表。通过调用ZK提供的创建节点的API,能够很容易创建一个全局唯一的path,这个path就可以作为一个名称。
阿里巴巴集团开源的分布式服务框架Dubbo中使用ZooKeeper来作为其命名服务,维护全局的服务地址列表,点击这里查看Dubbo开源项目。在Dubbo实现中: 服务提供者在启动的时候,向ZK上的指定节点/dubbo/${serviceName}/providers目录下写入自己的URL地址,这个操作就完成了服务的发布。 服务消费者启动的时候,订阅/dubbo/${serviceName}/providers目录下的提供者URL地址, 并向/dubbo/${serviceName} /consumers目录下写入自己的URL地址。 注意,所有向ZK上注册的地址都是临时节点,这样就能够保证服务提供者和消费者能够自动感应资源的变化。

另外,Dubbo还有针对服务粒度的监控,方法是订阅/dubbo/${serviceName}目录下所有提供者和消费者的信息。

分布式通知/协调
ZooKeeper中特有watcher注册与异步通知机制,能够很好的实现分布式环境下不同系统之间的通知与协调,实现对数据变更的实时处理。使用方法通常是不同系统都对ZK上同一个znode进行注册,监听znode的变化(包括znode本身内容及子节点的),其中一个系统update了znode,那么另一个系统能够收到通知,并作出相应处理

另一种心跳检测机制:检测系统和被检测系统之间并不直接关联起来,而是通过zk上某个节点关联,大大减少系统耦合。 另一种系统调度模式:某系统有控制台和推送系统两部分组成,控制台的职责是控制推送系统进行相应的推送工作。管理人员在控制台作的一些操作,实际上是修改了ZK上某些节点的状态,而ZK就把这些变化通知给他们注册Watcher的客户端,即推送系统,于是,作出相应的推送任务。
* 另一种工作汇报模式:一些类似于任务分发系统,子任务启动后,到zk来注册一个临时节点,并且定时将自己的进度进行汇报(将进度写回这个临时节点),这样任务管理者就能够实时知道任务进度。
总之,使用zookeeper来进行分布式通知和协调能够大大降低系统之间的耦合

集群管理与Master选举

集群机器监控:这通常用于那种对集群中机器状态,机器在线率有较高要求的场景,能够快速对集群中机器变化作出响应。这样的场景中,往往有一个监控系统,实时检测集群机器是否存活。过去的做法通常是:监控系统通过某种手段(比如ping)定时检测每个机器,或者每个机器自己定时向监控系统汇报“我还活着”。 这种做法可行,但是存在两个比较明显的问题:

1. 集群中机器有变动的时候,牵连修改的东西比较多。
2. 有一定的延时。

利用ZooKeeper有两个特性,就可以实时另一种集群机器存活性监控系统:

1. 客户端在节点 x 上注册一个Watcher,那么如果 x?的子节点变化了,会通知该客户端。
2. 创建EPHEMERAL类型的节点,一旦客户端和服务器的会话结束或过期,那么该节点就会消失。

例如,监控系统在 /clusterServers 节点上注册一个Watcher,以后每动态加机器,那么就往 /clusterServers 下创建一个 EPHEMERAL类型的节点:/clusterServers/{hostname}. 这样,监控系统就能够实时知道机器的增减情况,至于后续处理就是监控系统的业务了。 Master选举则是zookeeper中最为经典的应用场景了。

在分布式环境中,相同的业务应用分布在不同的机器上,有些业务逻辑(例如一些耗时的计算,网络I/O处理),往往只需要让整个集群中的某一台机器进行执行,其余机器可以共享这个结果,这样可以大大减少重复劳动,提高性能,于是这个master选举便是这种场景下的碰到的主要问题。

利用ZooKeeper的强一致性,能够保证在分布式高并发情况下节点创建的全局唯一性,即:同时有多个客户端请求创建 /currentMaster 节点,最终一定只有一个客户端请求能够创建成功。利用这个特性,就能很轻易的在分布式环境中进行集群选取了。

另外,这种场景演化一下,就是动态Master选举。这就要用到?EPHEMERAL_SEQUENTIAL类型节点的特性了。

上文中提到,所有客户端创建请求,最终只有一个能够创建成功。在这里稍微变化下,就是允许所有请求都能够创建成功,但是得有个创建顺序,于是所有的请求最终在ZK上创建结果的一种可能情况是这样: /currentMaster/{sessionId}-1 ,?/currentMaster/{sessionId}-2 ,?/currentMaster/{sessionId}-3 ….. 每次选取序列号最小的那个机器作为Master,如果这个机器挂了,由于他创建的节点会马上小时,那么之后最小的那个机器就是Master了。

在搜索系统中,如果集群中每个机器都生成一份全量索引,不仅耗时,而且不能保证彼此之间索引数据一致。因此让集群中的Master来进行全量索引的生成,然后同步到集群中其它机器。另外,Master选举的容灾措施是,可以随时进行手动指定master,就是说应用在zk在无法获取master信息时,可以通过比如http方式,向一个地方获取master。 在Hbase中,也是使用ZooKeeper来实现动态HMaster的选举。在Hbase实现中,会在ZK上存储一些ROOT表的地址和HMaster的地址,HRegionServer也会把自己以临时节点(Ephemeral)的方式注册到Zookeeper中,使得HMaster可以随时感知到各个HRegionServer的存活状态,同时,一旦HMaster出现问题,会重新选举出一个HMaster来运行,从而避免了HMaster的单点问题

分布式锁
分布式锁,这个主要得益于ZooKeeper为我们保证了数据的强一致性。锁服务可以分为两类,一个是保持独占,另一个是控制时序

所谓保持独占,就是所有试图来获取这个锁的客户端,最终只有一个可以成功获得这把锁。通常的做法是把zk上的一个znode看作是一把锁,通过create znode的方式来实现。所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁。 控制时序,就是所有视图来获取这个锁的客户端,最终都是会被安排执行,只是有个全局时序了。做法和上面基本类似,只是这里 /distribute_lock 已经预先存在,客户端在它下面创建临时有序节点(这个可以通过节点的属性控制:CreateMode.EPHEMERAL_SEQUENTIAL来指定)。Zk的父节点(/distribute_lock)维持一份sequence,保证子节点创建的时序性,从而也形成了每个客户端的全局时序。

分布式队列**
队列方面,简单地讲有两种,一种是常规的先进先出队列,另一种是要等到队列成员聚齐之后的才统一按序执行。对于第一种先进先出队列,和分布式锁服务中的控制时序场景基本原理一致,这里不再赘述。

第二种队列其实是在FIFO队列的基础上作了一个增强。通常可以在 /queue 这个znode下预先建立一个/queue/num 节点,并且赋值为n(或者直接给/queue赋值n),表示队列大小,之后每次有队列成员加入后,就判断下是否已经到达队列大小,决定是否可以开始执行了。这种用法的典型场景是,分布式环境中,一个大任务Task A,需要在很多子任务完成(或条件就绪)情况下才能进行。这个时候,凡是其中一个子任务完成(就绪),那么就去 /taskList 下建立自己的临时时序节点(CreateMode.EPHEMERAL_SEQUENTIAL),当 /taskList 发现自己下面的子节点满足指定个数,就可以进行下一步按序进行处理了。

Sharing Test code in Maven

Your pom in project B needs to include this plugin:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.5</version>
    <executions>
        <execution>
            <goals>
                <goal>test-jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Then, you can access it from project A like this:

<dependency>
    <groupId>XYZ</groupId>
    <artifactId>B</artifactId>
    <version>${project.version}</version>
    <type>test-jar</type>
    <scope>test</scope>
</dependency>

Changing ‘type’ to test-jar allows you to access test classes from that dependency.

Activiti数据库说明

概要说明

ACT_RE_*: ‘RE’表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。
ACT_RU_*: ‘RU’表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。
ACT_ID_*: ‘ID’表示identity。 这些表包含身份信息,比如用户,组等等。
ACT_HI_*: ‘HI’表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。
ACT_GE_*: 通用数据, 用于不同场景下。
ACT_EVT_*: EVT表示EVENT,目前只有一张表ACT_EVT_LOG,存储事件处理日志,方便管理员跟踪处理。

下面是各个表的大致意义:

意义 备注
ACT_EVT_LOG 事件处理日志
ACT_GE_BYTEARRAY 二进制数据表 保存流程定义图片和xml
ACT_GE_PROPERTY 属性数据表存储整个流程引擎级别的数据
ACT_HI_ACTINST 历史节点表 只记录usertask内容
ACT_HI_ATTACHMENT 历史附件表
ACT_HI_COMMENT 历史意见表
ACT_HI_DETAIL 历史详情表,提供历史变量的查询 流程中产生的变量详细,包括控制流程流转的变量等
ACT_HI_IDENTITYLINK 历史流程人员表
ACT_HI_PROCINST 历史流程实例表
ACT_HI_TASKINST 历史任务实例表
ACT_HI_VARINST 历史变量表
ACT_ID_GROUP 用户组信息表
ACT_ID_INFO 用户扩展信息表
ACT_ID_MEMBERSHIP 用户与用户组对应信息表
ACT_ID_USER 用户信息表
ACT_PROCDEF_INFO  流程定义数据表
ACT_RE_DEPLOYMENT 部署信息表
ACT_RE_MODEL 流程设计模型部署表 流程设计器设计流程后,保存数据到该表
ACT_RE_PROCDEF 流程定义数据表
ACT_RU_EVENT_SUBSCR throwEvent,catchEvent时间监听信息表
ACT_RU_EXECUTION 运行时流程执行实例表
ACT_RU_IDENTITYLINK 运行时流程人员表,主要存储任务节点与参与者的相关信息
ACT_RU_JOB 运行时定时任务数据表
ACT_RU_TASK 运行时任务节点表
ACT_RU_VARIABLE 运行时流程变量数据表

Mysql数据库复制及备份


一、mysql数据库复制概述

复制解决的基本问题是让一台服务器的数据和另外的服务器保持同步。一台主服务器可以连接多台从服务器,并且从服务器也可以反过来作为主服务器。主服务器和从服务器可以位于不同的网络拓扑中,还能对整台服务器、特定的数据库,甚至特定的表进行复制。

MySQL复制大部分都是向后兼容的。这意味着版本较新的服务器可以是版本较老的服务器的从服务器。但老版本的服务器通常不能是新版本号的服务器的从服务器。复制通常不会大幅增加主服务器的开销。它需要主服务器启用二进制日志,这或许会有较大的开销,但是出于备份的目的,无论如何这种开销都是需要的。

复制通常的用途有:数据分布、负载平衡、备份、高可用性和故障转移、测试mysql升级。


二、复制的工作原理

总体上来说,复制有以下三个步骤:

(a)主服务器把数据更改记录到二进制日志中。(这叫做二进制日志事件(binary
log events
)。)

(b)从服务器把主服务器的二进制日志事件拷贝到自己的中继日志(relay
log
)中。

(c)从服务器重放中继日志中的事件,把更改用到自己的数据上。

这三个步骤如下图所示:

第一步:在主服务器上记录二进制日志。在每个更新数据的事务完成之前,主服务器都会把数据更改记录到二进制日志中。即使事务在执行期间是交错的,mysql也会串行地把事务写入到二进制日志中。在把事件写入到二进制日志之后,主服务器告诉存储引擎提交事务。

第二步:从服务器把主服务器的二进制日志拷贝到自己硬盘上,进入所谓的“中继日志(relay log)中。

它首先启动一个工作线程,叫I/O线程。这个I/O线程开启一个普通的客户端连接,然后启动一个特殊的二进制日志转储进程。这个转储进程从主服务器的二进制日志中读取事件。它不会对事件进行轮询。如果它跟上了主服务器,就会进入休眠状态,并等待有新事件发生时主服务器发出的信号。I/O线程把事件写入从服务器的中继日志中。

第三步:SQL从线程处理了该过程的最后一部分。该线程读取了中继日志,并且重放其中的事件,然后更新从服务器的数据。由于这个线程能跟上I/O线程,所以,中继日志一般都是在操作系统的缓存中,因此中继日志的开销很低。同时SQL线程执行的事件也可以被写入从服务器自己的二进制日志中。


三、创建复制以及配置主、从服务器

创建复制主要分为下面几个步骤:

1、  在每一台服务器上建立复制账号。

2、  配置主、从服务器。

3、  指导从服务器进行连接与复制。

下面以实际操作的例子来进一步说明复制的创建。

1、  平台说明:

系统环境:ubuntu10.10

软件版本:mysql-5.5.25

2、  Mysql数据库说明:

在两台不同的计算机里面安装好mysql服务器。

主服务器IP192.168.1.100

从服务器IP192.168.1.104

下面将按照创建复制的步骤进行说明

第一步:在每一台服务器上建立复制账号

Mysql有一些特殊的权限允许复制进程运行。从I/O线程运行在从服务器上,它创建了到主服务器的连接。基于此,在主服务器上就必须创建一个用户账户并且给它合适的权限,这样I/O线程就可以以这个用户的身份连接到主服务器,并且读取它的二进制日志。

上述命令在主服务器上创建一个用户名为repl的账号。这里把用户限制到了本地网络。

第二步:配置主、从服务器

修改主服务器的配置文件my.cnf:加入如下设置

sync_binlog = 1

log-bin = mysql-bin

server-id = 10

innodb_support_xa =1

在主服务器上最重要的二进制日志设置是sync_binlog,这使得mysql在每次提交事务的时候把二进制日志的内容同步到磁盘上,即使服务器崩溃也会把事件写入日志中。

如果不想在服务器崩溃后表被破坏,所以我们使用mysql默认的存储引擎InnoDB

而且必须显式地定义唯一的服务器ID。这里为了避免产生混淆,用10代替1。因为1通常是服务器的默认值。所以使用1容易引起混淆,并导致和没有服务器ID的服务器冲突。

如果log_bin选项在主服务器的配置文件中没有定义,那就重启mysql

验证二进制日志文件已经被创建出来,可以运行如下指令:

从服务器也需要和主服务器类似的配置,并且也需要在从服务器上重启mysql

log-bin=mysql-bin

server-id  = 2

relay_log  = mysql-relay-bin

log_slave_updates = 1

read_only  = 1

skip_slave_start

以上配置单从技术上来说,有些选项是不需要的。实际上,从服务器只有server_id参数是必须的,这里我们也开启了log_bin,并且显式地给了二进制文件一个名字。同时,把主、从服务器的文件名设置成一样的,这样做的目的是便于把从服务器变为主服务器。

此外,还添加了两个其他的可选配置参数:relay_log(定义中继日志的位置和文件名)和log_slave_update(使从服务器把复制的事件记录到自己的二进制日志中)。

Skip_slave_start选项会阻止从服务器在崩溃后自动启动,可以让管理员有机会去修复服务器。

第三步:指导从服务器进行连接与复制

这一个步骤是告诉从服务器如何连接到主服务器并中继其中二进制日志。这一个步骤中,不要直接在配置文件my.cnf里配置,而是应该使用CHANGE MASTER TO命令,在从服务器上输入如下所示命令:

参数说明:

MASTER_HOST:指主服务器IP

MASTER_USER:指复制账号用户名。

MASTER_PASSWORD:指复制用户密码。

MASTER_LOG_FILE:指复制的二进制日志名。

MASTER_LOG_POS:指二进制日志的偏移量。

输入上述指令没有出错的话,将会有成功的提示。

检测输出:

输入上面这条命令,将会出现如下所示内容:

由上图可以看到,此时,从服务器I/O线程和SQL线程正在运行,并且Seconds_Behind_Master不再是NULL(如果想看到是NULL的话,就先STOP
SLAVE
;然后再SHOW SLAVE STATUS\G)。I/O线程正在等待主服务器的事件,这意味着它已经提取了主服务器的所有二进制日志。日志位置已经增加了,表示一些事件已经提取并执行过了。这时,如果在主服务器上做一些数据更改,那么将会看见从服务器上的文件和位置参数都增加了。些时就可以在从服务器上看到数据库改变了。

查看主、从服务器工作线程:

    当然啦,这里显示的例子,是来自运行了一些日子的服务器,所以I/O线程Time列值比较大。从服务器的SQL线程已经空闲了11秒,这表示已经有11秒没有发生事件重放了。Info显示正在执行的查询,目前正在执行的查询为NULL

前面所述都是假设主、从服务器刚刚安装好,使用的数据都是默认的初始化数据,所以两台服务器默认的有相同数据,并且也知道了主服务器的二进制日志。但如果是主服务器已经运行了一段时间了,然后用一台新安装的从服务器进行同步,那么此时,从服务器还没有主服务器的数据。

所以,在复制数据之前,必须用主服务器初始化一台从服务器。为了让从服务器和主服务器同步数据,需要下面三个条件:

1、  某个时间点上主服务器数据的快照。

2、  主服务器当前的日志,以及从快照时间点以来精确的日志字节偏移量。这两个值叫做日志文件坐标,它们共同确定了二进制日志的位置。可以使用SHOW
MASTER STATUS
查找主服务器的日志文件坐标。

3、  从快照时间到现在的主服务器二进制日志文件。

这里,由于我们只用了mysql默认的存储引擎InnoDB,所以,可以使用下面的命令来转储主服务器的所有内容,把它装入从服务器中,并且把从服务器的坐标改成主服务器二进制日志的相应位置:

$mysqldump –h 192.168.1.100 –u repl –p123456 –single-transaction –all-databases –master-data=0 | mysql –p

这样,就可以把主服务器上的数据同步到从服务器上了。

至此,当主服务器上有数据更改,从服务器上的数据也会发生更改。我们管这种数据复制模式叫做主—从模式。

但现实中,通常需要的是两台服务器,当其中一台服务器的数据发生变化,将会把数据同步到另一台服务器中。这种模式叫主—主模式。

配置这种模式,只要将前面所述的主、从服务器配置反过来设置一次就可以了。主服务器和从服务器的设置是对称的。

当设置好后,就可以实现主—主同步复制了。


四、其他复制模式简介

1、一主多从模式

刚才配置从服务器的时候加入了log_slave_updates选项,这样就可以把一台从服务器变成主服务器了,它会指导mysql把自己执行的事件写到二进制日志中,然后自己的从服务器就可以取得这些事件并执行它。如下图所示:

在这种情形下,主服务器的改变导致事件被写入到二进是中。第1个从服务器提取并执行这个事件。

一般来说,这个时候事件的生命周期就结束了,但是因为log_slave_updates 打开了,所以,从服务器就会把它写入到自己的二进制日志中。那么第2个从服务器就可以再次取得这个事件并执行它了。

2、复制过滤器

在主、从服务器的数据复制同步过程中,我们可以有选择性的复制同步一部份数据,这时就要用到复制过滤器。复制过滤器有两种:

(a)主服务器上把事件从二进制日志中过滤掉的过滤器。

(b)从服务器上把事件从中继日志中过滤掉的过滤器。

如下图所示:

控制二进制日志过滤的选项是binlog_do_dbbinlog_ignore_db。但通常不要开启它们。

在从服务器上,replicate_*选项在从服务器SQL线程从中继日志中读取事件的时候进行过滤。可以复制,或者忽略一个或多个数据库。

3、复制拓扑

Mysql数据库的复制拓扑中,必须遵守下面的基本原则:

(a)一个mysql从服务器只能有一个主服务器。

(b)每个从服务器有唯一的服务器ID

(c)一个主服务器可以有很多从服务器。

(d)如果打开了log_slave_update,一个从服务器就能把主服务器的改动传播下去,并且能成为其他从服务器的主服务器。

下面列出一部份复制拓扑的结构示意图:

一台主服务器和多个从服务器

  

拥有从服务器的环形结构

 

    除上述所讲到的复制拓扑外,不家其他一些拓扑,这里不一一叙述。具体在现实工作环境中,要使用哪一个复制模式,将要按照需求进行选择配置。


五、备份与还原

备份数据是数据库管理中最常用的操作。为保证数据库中数据的安全,数据库管理员需要定期的进行数据库备份。当数据库遭到破坏时,通过备份文件来还原数据库。

1、使用mysqldump命令备份

Mysqldump命令可以将数据库中的数据备份成一个文本文件。表的结构和表中的数据将存储在生成的文本文件中。

Mysqldump命令的工作原理:它先查出需要备份的表的结构,再在文本文件中生成一个CREATE语句。然后,将表中的所有记录转换成一个INSERT语句。这些CREATE语句和INSERT语句都是还原时使用的。还原数据时就可以使用其中的CREATE语句来创建表,使用其中的INSERT语句来还原数据。

使用mysqldump命令备份一个数据库的基本语法如下:

Mysqldump –u username –p dbname table1 table2……>BackupName.sql

参数说明:

Dbname:参数表示数据库的名称;

Table1table2:表示表的名称,没有该参数时将备份整个数据库;

BackupName.sql:表示备份文件的名称,文件名前面可以加上一个绝对路径。一般都会将数据库备份成一个后缀名为sql的文件。

但是mysqldump命令备份的文件并非一定要求后缀名为.sql,备份成其他格式的文件也是可以的,但是通常情况下是备份成后缀名为.sql的文件,因为,后缀名为.sql的文件给人的第一感觉就是与数据库有关的文件。

使用mysqldump备份多个数据库:

Mysqldump –u username –p –databases dbname1 dbname2…… > BackupName.sql

可以看到,备份多个数据库和备份一个数据库不同,备份多个数据库要加上“–databases”这个选项,然后后面跟多个数据库的名称。

使用mysqldump备份所有的数据库:

Mysqldump –u username –p –all-databases > BackupName.sql

2、远程备份

远程备份可以分为两种情况:

第一:两台服务器没有进行数据同步设置、从服务器数据跟不上主服务器数据更新或者设置数据同步的时候不是完全数据同步而只份数据同步。

第二:两台服务器进行了数据同步设置、服务器数据几本上不落后主服务器数据并且设置数据同步的时候是完全数据同步。

下面先讨论第一种情况。假设,需要备份的服务器主机IP为:192.168.1.100,首先在该主机上为mysql系统添加root远程登录权限:

mysql> grant all privileges on *.* to  root@’%’ identified by ‘123456;

此时在远端的服务器上就可以登录主机服务器了:

Mysql –h 192.168.1.100 –u root –p

然后输入密码后就可以登录进主服务器的root用户了。

远程备份全部数据库:

 Mysqldump –h 192.168.1.100 –u root –p123456 –all-databases >/home/Backup.sql

这样就可以把远程主机上的数据库数据备份到本地设备上了。

第二种情况比较简单,因为两台服务器数据是完全同步的,也就是说两台服务器上的数据库数据是一致的,所以,对于这种情况,我们只需要用mysqldump命令按本地备份模式进行备份就可以了。

3、数据还原

当管理员的非法操作和计算机的故障等都会破坏数据库文件。当数据库遭到这些意外时,可以通过备份文件将数据库还原到备份时的状态。这样可以将损失降低到最小。

前面说了,我们是用mysqldump命令将数据库中的数据备份成一个文本文件。并且通常来说这个文件会以.sql后缀名结尾。需要还原的时候,可以使用mysql命令来还原备份的数据。

备份文件中通常包含CREATE语句和INSERT语句。Mysql命令可以执行备份文件中的CREATE语句和INSERT语句。通过CREATE语句来创建数据库和表。通过INSERT语句来插入备份的数据。从而达到还原的目的。

Mysql命令的基本语法如下:

Mysql –u root –p [dbname] < backup.sql

参数说明:

Dbname参数表示数据库名称。该参数可选,可以指定数据库名,也可以不指定。指定数据库名时,表示还原该数据库下的表。不指定数据库名时,表示还原特定的一个数据库。

 

mysql show database size

SELECT table_schema                                        "DB Name", 
   Round(Sum(data_length + index_length) / 1024 / 1024, 1) "DB Size in MB" 
FROM   information_schema.tables 
GROUP  BY table_schema;