百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

基于Redis+ApacheIgnite+分布式文件系统的状态管理集群!

mhr18 2024-11-18 14:31 20 浏览 0 评论

扩展为集群

随着业务的增长,数据量越来越大,单一机器逐渐不能满足日益增长的数据量。

与此同时,数据量变大后,程序的性能也开始变得越来越差,以至于最后不可接受。所以,我们必须未雨绸缪,让流计算系统能够伴随业务不断成长,这就要求系统具备水平扩展的能力。

在实时流计算系统中,不管是使用诸如Kafka消息中间件的分区功能,还是依赖于诸如Flink KeyedStream这样的流计算框架本身的分区流能力,最终都能比较轻松、方便地实现计算能力的水平扩展。

但是,对于计算中的状态数据来说,实现计算能力的水平扩展不是一件非常容易的事情。这是因为,状态数据很多时候是需要共享和同步的,如对于分别在两个计算节点上计算的事件,它们可能需要同时访问相同的数据。即使我们先不考虑并发安全的问题,这也意味着相同的数据会被两个不同的节点访问。也就是说,至少有一个节点的跨网络远程访问是不可避免的。

而在前面关于时间维度聚合特征计算和关联图谱特征计算的具体实现中,我们不难发现,它们都是严重依赖于大量状态访问的,甚至有时候一次窗口计数的查询会访问几个甚至几十个子窗口的寄存器。如果不能避免或优化这些访问,那么程序的性能势必会严重受累于跨网络的远程状态访问。所以,我们有必要专门讨论将状态的存储和管理,从单节点扩展为分布集群时的一系列问题。本节将讨论3种不同的状态集群方案,它们分别代表了一种典型的分布式计算架构设计思路,可谓是各有千秋。

基于Redis的状态集群

图5-2展示了使用Redis集群实现状态分布式存储和管理的原理。

当采用Redis集群实现分布式状态存储和管理时,流计算集群和Redis集群节点是分离开的。流计算集群中的每个节点都可以任意访问Redis集群中的任何一个节点。这样的架构有一个非常明显的好处,即计算和数据是分离开的。我们在任何时候,可以任意地新增流计算节点,而不会影响Redis集群。反过来,我们也可以任意地新增Redis节点,而不会影响流计算集群。

这样的体系结构也有缺点。以“过去一天同一用户的总交易金额”这个时间维度聚合特征的计算为例。如果我们采用与上面相同的算法,就需要先将“1天”分成了24个“1小时”的子窗口,这样在查询计算时将有24次的Redis GET操作。假设这24个子窗口的状态数据是分散在6台Redis上的。如果不做任何优化设计,那么这一个特征计算就需要24次I/O操作,而且涉及与6台不同服务器的远程通信,这势必会对性能造成极大的影响。针对以上问题,我们该怎么办呢?我们可以根据“局部性原理”和“批次请求处理”的思想来优化解决方案。

局部性原理

局部性原理(见图5-3)是指计算单元在访问存储单元时,所访问的存储单元应该趋向于聚集在一个局部的连续区域内。利用局部性原理可以更加充分地提高计算资源的使用效率,从而提高程序的性能。

前面讲到在“过去一天同一用户的总交易金额”这个特征计算中,我们可能需要访问6台Redis节点上的数据。这是因为默认情况下,Redis集群将数据按照key做hash计算后分散到各个槽(slot)中,而槽又分布在各个Redis节点上。如果我们能够让“同一用户”的状态数据保存在相同的槽里,就可以让这批数据存在于相同的Redis节点上。

Redis的官方集群方案Redis Cluster提供了贴心的标签(tag)功能,允许只使用key中的部分字段来计算hash值。具体而言,如果hash_tag指定为“{}”,那么当key含有“{}”的时候,就不使用整个key来计算hash值,而只对“{}”包括的部分字段计算hash值。例如,在使用标签功能后,每个小窗口内记录这个窗口交易总金额的key如下所示:

$event_type.{$userid}.$window_unit.$window_index

经过标签化的key,相同用户的状态数据会落在相同的Redis节点。

这样,我们只需要访问一个Redis节点即可。

现在数据位于同一个节点上了,那这有什么好处呢?好处多着呢。

首先,我们可以放心大胆地使用Redis的各种多键指令了,如MGET、MSET、SUNION和SUNIONSTORE等。这些指令在操作过程中可以一次访问多个键,从而提高指令执行效率。而如果这些key不在同一个Redis节点上,则这些指令是不能使用的。其次,我们可以充分发挥Redis的pipeline功能。通过Redis的pipeline功能,可以一次性发送多条指令,这些指令间可以没有任何依赖关系。当执行完后,这些指令的结果一次性返回。通过这种批次传递和执行指令的方式,Redis减少了平均每条指令执行时不必要的网络开销,提升了执行效率。同样地,如果这些数据不在同一个Redis节点上,我们就不能使用pipeline功能。

所以,将相关数据放在相同的节点上,给我们留下更多的优化空间。经过上述的优化设计后,原本需要24次I/O操作的特征计算,最优情况下只需要一次I/O操作。这就是局部性原理的魅力所在!

当然,使用局部性原理也可能出现数据在集群节点上分布不均匀的问题。所以,在选择分区标签时,应该尽量分得更细、更均匀些,这样可以减小数据倾斜的问题。

批次请求处理

批次请求处理是指将多个请求收集起来后,一次性成批处理的过程。批次请求处理可以降低均摊在每条消息处理时非有效用于消息处理的资源和时间。Redis的pipeline功能就是一种批次请求处理的技术,但是我们不能仅限于Redis的Pipeline功能。实际上,任何与I/O相关的操作都可以借鉴这种批次处理的思想,如RPC(远程过程调用)、REST请求、数据库查询等。

在实际开发过程中,对请求做批次化处理本身并不是非常复杂的过程,比较麻烦的是应该怎样将分布在程序各个地方的请求收集起来。针对这个问题,我们可以使用队列和CompletableFuture的异步方案,图5-4描述了这个方案的具体实现方法。

当请求发起时,将请求提交给队列后获取一个CompletableFuture对象。而另外一个线程等着从这个队列中取出请求。当该线程取出的请求达到一定数量或者等待超过一定时间时,将取出的这批请求封装成批次请求,发送给请求处理服务器。当批次请求返回后,将批次结果拆解开,再依次使用CompletableFuture的complete函数将结果交给各个请求发起者。这样就实现了请求的批次化处理。

批次化处理的好处在于提高了请求处理的吞吐量,降低了每条请求平均响应时延,但是因为使用了队列和异步的方案,也有可能会提高特定某条请求的响应时延。因此,在实际开发中,读者需要综合考虑自己的场景选择最合适的方案。

基于Apache Ignite的状态集群

图5-5描述了Apache Ignite集群用于状态存储和管理的架构。从该架构图可以看出,当采用Apache Ignite来实现状态管理时,计算节点和数据节点是耦合在一起的,它们在相同的JVM内运行。每个ApacheIgnite节点会保存全部集群数据中的一部分,流计算节点通过其嵌入的Apache Ignite节点来访问状态数据。而Apache Ignite数据格点自身的设计和实现机制,允许计算尽量只需要访问本地节点上的数据以完成计算任务,减少数据在网络间的流动。这种设计方案充分利用了ApacheIgnite提供的数据格点能力,是一种典型的网格计算架构。

采用Apache Ignite数据格点的方案,可以让我们不必过多考虑数据分区问题。Apache Ignite会自行处理数据局部性及计算和数据亲和性的问题。Apach.Ignite提供的各种计算和查询接口屏蔽了分布式数据和分布式计算的复杂性,为我们开发分布式系统带来极大的便利性。网格计算中的所有节点都是平等的,当需要水平扩展集群时,只需要将新的节点添加到网格中即可。

不过将计算节点和数据节点耦合在同一个JVM后,增加了单一节点的复杂性,同时使计算资源的分配、管理和监控等变得更加复杂。这点需要读者在做方案选型时根据具体场景和需求自行定夺。

基于分布式文件系统的状态管理集群

除了上面两种状态管理的集群外,还有一种基于分布式文件系统的状态管理集群,这是一种非常典型的分布式状态管理方案。Flink的状态管理采用的就是这种方案。

图5-6描述了基于分布式文件系统的状态管理集群。在这种分布式状态管理方案中,流计算节点针对状态的操作完全在本地完成,不涉及任何远程操作。但如果只是这样,那当需要扩展或收缩集群的节点数时,怎么保证能够读取到原来的状态信息呢?因此在每个节点上,有专门的线程定期或在必要的时候(如任务关闭前),对状态进行checkpoint。所谓checkpoint,是指将本地状态后端的数据做快照(snapshot)之后,保存到分布式文件系统的过程。当集群在节点数变化后再重启时,各个节点首先从分布式文件系统中读取其所负责数据分片所在的快照,再将快照恢复到状态后端,这样各个节点就获得重启前的状态数据了,之后的计算又可以完全在本地完成。

这种方案的优势在于,流计算节点对状态的操作在本地完成,不需要任何远程操作。这样本地状态后端的选择可以非常丰富,给性能优化留下极大空间。例如,Flink目前已经支持内存、文件系统和RockDB 3种状态后端。不过这种方案也有一个缺点,即不能在运行时动态扩展或缩小集群。当集群节点数变更时,需要重启集群。对应在Flink中,当需要改变算子的并行度(operator parallelism)时,必须重启作业。

本篇文章给大家讲解的内容是实时流计算的状态管理:扩展为集群

下篇文章给大家讲解的内容是开源流计算框架:Apache Storm

相关推荐

【推荐】一个开源免费、AI 驱动的智能数据管理系统,支持多数据库

如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!.前言在当今数据驱动的时代,高效、智能地管理数据已成为企业和个人不可或缺的能力。为了满足这一需求,我们推出了这款开...

Pure Storage推出统一数据管理云平台及新闪存阵列

PureStorage公司今日推出企业数据云(EnterpriseDataCloud),称其为组织在混合环境中存储、管理和使用数据方式的全面架构升级。该公司表示,EDC使组织能够在本地、云端和混...

对Java学习的10条建议(对java课程的建议)

不少Java的初学者一开始都是信心满满准备迎接挑战,但是经过一段时间的学习之后,多少都会碰到各种挫败,以下北风网就总结一些对于初学者非常有用的建议,希望能够给他们解决现实中的问题。Java编程的准备:...

SQLShift 重大更新:Oracle→PostgreSQL 存储过程转换功能上线!

官网:https://sqlshift.cn/6月,SQLShift迎来重大版本更新!作为国内首个支持Oracle->OceanBase存储过程智能转换的工具,SQLShift在过去一...

JDK21有没有什么稳定、简单又强势的特性?

佳未阿里云开发者2025年03月05日08:30浙江阿里妹导读这篇文章主要介绍了Java虚拟线程的发展及其在AJDK中的实现和优化。阅前声明:本文介绍的内容基于AJDK21.0.5[1]以及以上...

「松勤软件测试」网站总出现404 bug?总结8个原因,不信解决不了

在进行网站测试的时候,有没有碰到过网站崩溃,打不开,出现404错误等各种现象,如果你碰到了,那么恭喜你,你的网站出问题了,是什么原因导致网站出问题呢,根据松勤软件测试的总结如下:01数据库中的表空间不...

Java面试题及答案最全总结(2025版)

大家好,我是Java面试陪考员最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Spring、MySQL、JVM、Redis、Linux、Sprin...

数据库日常运维工作内容(数据库日常运维 工作内容)

#数据库日常运维工作包括哪些内容?#数据库日常运维工作是一个涵盖多个层面的综合性任务,以下是详细的分类和内容说明:一、数据库运维核心工作监控与告警性能监控:实时监控CPU、内存、I/O、连接数、锁等待...

分布式之系统底层原理(上)(底层分布式技术)

作者:allanpan,腾讯IEG高级后台工程师导言分布式事务是分布式系统必不可少的组成部分,基本上只要实现一个分布式系统就逃不开对分布式事务的支持。本文从分布式事务这个概念切入,尝试对分布式事务...

oracle 死锁了怎么办?kill 进程 直接上干货

1、查看死锁是否存在selectusername,lockwait,status,machine,programfromv$sessionwheresidin(selectsession...

SpringBoot 各种分页查询方式详解(全网最全)

一、分页查询基础概念与原理1.1什么是分页查询分页查询是指将大量数据分割成多个小块(页)进行展示的技术,它是现代Web应用中必不可少的功能。想象一下你去图书馆找书,如果所有书都堆在一张桌子上,你很难...

《战场兄弟》全事件攻略 一般事件合同事件红装及隐藏职业攻略

《战场兄弟》全事件攻略,一般事件合同事件红装及隐藏职业攻略。《战场兄弟》事件奖励,事件条件。《战场兄弟》是OverhypeStudios制作发行的一款由xcom和桌游为灵感来源,以中世纪、低魔奇幻为...

LoadRunner(loadrunner录制不到脚本)

一、核心组件与工作流程LoadRunner性能测试工具-并发测试-正版软件下载-使用教程-价格-官方代理商的架构围绕三大核心组件构建,形成完整测试闭环:VirtualUserGenerator(...

Redis数据类型介绍(redis 数据类型)

介绍Redis支持五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sortedset:有序集合)。1、字符串类型概述1.1、数据类型Redis支持...

RMAN备份监控及优化总结(rman备份原理)

今天主要介绍一下如何对RMAN备份监控及优化,这里就不讲rman备份的一些原理了,仅供参考。一、监控RMAN备份1、确定备份源与备份设备的最大速度从磁盘读的速度和磁带写的带度、备份的速度不可能超出这两...

取消回复欢迎 发表评论: