6.1典型应用场景及实现

6.1.1 数据发布/订阅

数据分布/订阅(publish/subscribe)系统,即所谓的配置中心,顾名思义就是发布者将数据发布到Zookeeper的一个或一系列节点上,供订阅者进行数据订阅,进而达到动态获取数据的目的,实现配置信息的集中式管理和数据的动态更新。

Zookeeper采用的推拉相结合的方式:客户端向服务端注册自己需要关注的节点,一旦该节点的数据发生变更,那么服务端就会向相应的客户端发送Watcher事件通知,客户端接收到这个消息通知之后,需要主动到服务端获取最新的数据。

  • 数据库切换场景
    • 配置存储:将连接信息写到zk节点中;
    • 配置获取:集群机器启动时,会从zk节点中获取,并注册Wathcer监听节点变更事件;
    • 配置变更:数据库切换的时候,客户端获取到变更通知后,就可以重新进行最新数据的获取。

6.1.2 负载均衡

负载均衡是一种相当常见的计算机网络技术,用来对集群、网络连接、CPU、磁盘驱动器或者其他资源进行分配负载,已达到优化资源使用、最大化吞吐率、最小化响应时间和避免过载的目的。

一种动态的DNS服务
  • 域名配置:在ZK上创建一个节点来进行域名配置,如/DDNS/app1/server.app1.com,每个应用都可以自己创建这个根节点
  • 域名解析:在DDNS中,域名的解析过程都是由每一个应用自己负责的。通常应用都会首先从域名节点中获取一份IP地址和端口的配置,进行自行解析。同时每个应用还会在域名节点上注册一个数据变更Watcher监听,以便及时收到域名变更的通知。
  • 域名变更:运行过程中,难免会碰上域名对应的IP地址或是端口变更,这个时候就需要进行域名变更操作。
自动化的DNS服务

上面的实现过程中的问题,当ip地址发生变更的时候,我们还是需要手动去修改域名节点上的IP地址或端口。接下来我们看看如何自动化的实现服务的自动化定位,如下是其系统架构图: 首先介整个动态DNS系统的架构体系中几个比较重要的组件机器职责:

  • Register集群负责域名的动态注册
  • Dispatcher集群负责域名解析
  • Scanner集群负责检测以及维护服务状态
  • SDK提供各种语言的系统接入协议,提供服务注册以及查询接口
  • Monitor负责收集服务信息以及对DDNS自身状态的监控
  • Contorller是一个后台管理的console,负责授权管理、流量控制、静态配置服务和手动屏蔽服务等功能。

整个系统的核心当然是Zookeeper集群,负责数据的存储以及一些分布式协调。

  • 域名注册:每个服务者提供者在启动的过程中,都会把自己的域名信息注册到Register集群中取。
  • 域名解析:服务消费者在使用域名的时候,会向Dispatcher发出域名解析请求。
  • 域名探测:指DDNS系统需要对域名下所有注册的IP地址和端口的可用性进行检测。
6.1.3 命名服务

在分布式系统中,被命名的实体通常都是集群中的机器、提供的服务地址或者远程对象等————这些都可以统称为名字。zk提供的命名服务,能够帮助应用系统通过一个资源引用的方式来实现对资源的定位与使用。

6.1.4 分布式协调/通知

对于一个在多台机器上部署运行的应用而言,通常需要一个协调者来控制整个系统的运行流程,如事务处理、机器间的协调等。同时,引入这样一个协调者,便于将分布式协调的职责从应用中分离出来,从而可以大大减少系统之间的耦合性,而且能够显著提高系统的可扩展性。

ZK中持有的Watcher注册与异步通知机制,能够很好地实现分布式环境下不同机器,甚至是不同系统之间的协调与通知,从而实现对数据变更的实时处理。

Mysql数据复制总线:Mysql_Replicator

Mysql数据复制总线是一个实时数据复制框架,用于在不同的Mysql数据库实例之间进行一步数据复制和数据变化的通知。整个系统是由Mysql数据库集群、消息队列系统、任务管理监控平台以及ZK集群等组件共同构成的一个包含数据生产者、复制管道和数据消费者等部分的数据总线系统,下图是整体结构:

zk主要负责进行一系列的分布式协调工作,在具体的实现上,根据功能将数据复制组件划分为三个核心子模块:Core、Server和Monitor,每个模块分别为一个单独的进程,通过ZK进行数据交换。

  • Core 实现了数据复制的核心逻辑,其将数据复制封装成管道,并抽象出生产者和消费者两个概念,其中生产者通常是Mysql数据库的Binlog日志。
  • Server 负责启动和停止复制任务。
  • Monitor负责监控任务的运行状态,如果在数据复制期间发生异常或出现故障会进行告警。

三个子模块之间的关系如图所示: 每个模块作为独立的进程运行在服务端,运行时的数据和配置信息均保存在ZK上,We控制台通过ZK上的数据获取到后台进行的数据,同时发布控制信息。

详情可研究阿里开源的Canal组件

一种通用的分布式系统机器间通信方式

绝大部分的分布式系统中,系统机器间的通信无外乎心跳检测,工作进度汇报和系统调度这三种类型:

  • 心跳检测: 基于ZK的临时节点特性,可以让不同的机器都在ZK的一个指定节点下创建临时子节点,不同的机器之间可以根据这个临时节点来判断对应的客户端机器是否存活。
  • 工作进度汇报:在zk上选择一个节点,每个任务客户端都在这个节点下面创建临时子节点,这样便可以实现两个功能:
    • 通过临时节点是否存在来确定任务机器是否存活,
    • 各个任务机器会实时地将自己的任务执行进度写到这个临时节点上去,以便中心系统能够实时地获取到任务的执行进度。
  • 系统调度:一个分布式系统由控制台和一些客户端系统两部分组成,控制台的职责就是需要将一些指令信息发送给所有的客户端,以控制它们进行相应的业务逻辑。后台管理人员在控制台上做的操作,其实就是修改zk上某些节点数据,而zk通过已事件通知的形式发送给了对应的订阅客户端。
6.1.5 集群管理

集群管理包括集群监控与集群控制两大块,前者侧重对集群运行时状态的收集,后者则是对集群进行操作与控制。主要通ZK如下的两大特性:

  • 客户端如果对ZK的一个数据节点注册Watcher监听,那么当该数据节点的内容或是其子节点列表发生变更时,ZK服务器就会向订阅的客户端发送变更通知。
  • 对在ZK上创建的临时节点,一旦客户端与服务器之间的会话失效,那么该临时节点也就会被自动清除。
分布式日志收集系统

在一个典型的日志系统的架构设计中,整个日志系统会把所有需要谁的日志机器分为多个组件,每个组别对应一个收集器,这个收集器其实就是一个后台机器,用于收集日志。对于大规模的分布式日志收集系统场景,通常需要解决如下两个问题:

  • 变化的日志源机器:在生产环境中,伴随着机器的变动,每个应用的机器几乎每天都是在变化的,也就是说每个组别中的日志源机器通常是在不断变化的。
  • 变化的手机器机器:日志收集系统自身也会有机器的变更或扩容,于是会出现新的收集器机器退出的情况。

总结:如何快速、合理、动态地为每个收集器分配对应的日志源机器,这也成为了整个日志系统正确稳定运转的前提,这也是日志收集过程中最大的技术调整之一。这种情况下,引入zk是一个不错的选择。

Flume OG日志收集系统

对于Flume OG ,可以说他是一个分布式日志收集系统,有Mater概念,依赖于zookeeper,以下是其架构图: Agent用于采集数据,agent是flume中产生数据流的地方,同时,agent会将产生的数据流传输到collector。对应的,collector用于对数据进行聚合,往往会产生一个更大的流。

不过目前已经不再使用了Flume NG,它摒弃了Master和zookeeper,collector也没有了,web配置台也没有了

6.1.6 Master选举

分布式最核心的特性就是能够将具有独立计算能力的系统单元部署在不同的机器上,构成一个完整的分布式系统。而与此同时,实际场景中往往也需要在这些分布在不同机器上的独立系统单元中选出一个所谓的“老大”,在计算机科学中,我们称之为Master。 在分布式系统中,Master往往用来协调集群中其他系统单元,具有对分布式系统状态的变更的决定权。

6.1.6 分布式锁

分布式锁是控制分布式系统之间同步访问共享资源的一种方式。

排他锁

排他锁的核心是如何保证当前有且仅有一个事务获得锁,并且锁被释放后,所有正在等待获取锁的事务都能够被通知到。在zk中,通过其上的一个数据节点表示锁。

共享锁

共享锁,又称为读锁,同样是一种基本的锁类型。如果事务T1对数据对象O1加上了共享锁,那么当前事务只能对O1进行读取操作,其他事务也只能对这个数据对象加共享锁——直到该数据对象的所有共享锁都被释放。 详情

results matching ""

    No results matching ""