解决方案:用了8年MQ!聊聊消息队列的技术选型,哪个最香!
优采云 发布时间: 2022-11-27 05:19解决方案:用了8年MQ!聊聊消息队列的技术选型,哪个最香!
说到消息队列,心里还是有些波澜。
消息队列、缓存和分库分表是高并发解决方案的三把剑,而消息队列是我最喜欢的,也是我思考最多的技术。
下面分享一下我在消息队列这四个阶段的故事,也是对自己技术成长经历的回顾。
1 认识ActiveMQ1.1异步&解耦
2011年初,我在一家互联网彩票公司做研发。
我负责用户中心系统,提供用户注册、查询、修改等基本功能。用户注册成功后,需要给用户发送一条短信。
因为本来就是面向过程的编程,所以我把新建用户模块和短信发送模块组合在一起。
一开始还好,但是慢慢的问题就出现了。
第一个问题,我可以采取线程池的方式来做,主要是异步的。但是第二个问题让我很困惑。
于是向技术经理请教,他让我引入消息队列来解决这个问题。
这时候我才明白,消息队列的核心功能就是异步和解耦。
1.2 调度中心
彩票系统的业务比较复杂。在彩票订单的生命周期中,有创建、子订单拆分、出票、中奖计算等多个环节。每个环节需要不同的业务处理,每个系统都有自己独立的表,业务功能相对独立。如果每个应用程序都修改订单主表中的信息,那将是相当混乱的。
该公司的建筑师设计了调度中心的服务。调度中心的职责是维护订单核心状态机、订单奖励流程、彩票核心数据的生成。
调度中心通过消息队列、票务网关、奖品计算服务等系统进行信息传递和交换。
在我当时幼小的眼里,这种设计就像是水滴对战人类舰队,降维打击。
随着对业务理解的不断加深,我隐约感觉到:“好的架构是简洁的,应该是易于维护的”。
当彩票业务日均交易量几千万的时候,调度中心只有两个研发和维护人员。调度中心源码中的业务逻辑、日志、代码规范都很优秀。
在以后的编程生活中,我也会下意识地模仿调度中心的编码方式,“别耍花样,代码是给人看的”。
1.3 重启大法
随着彩票业务的爆发式增长,日新闻量从30万条猛增到150万到200万条左右,一切似乎都趋于平稳。
某一天,双色球投注结束,调度中心无法消费消息队列中的数据。消息总线处于发送状态,没有接收状态。整个技术团队都处于极度焦急的状态,“如果不能出票,那将是几百万的损失,如果用户中了两个双色球?那就是几千万了。” 每个人都急得像热锅上的蚂蚁。
这也是整个技术团队第一次遇到消费积累,大家都没有经验。
首先想到的是多部署几个调度中心服务。部署完成后,调度中心消费了上千条消息还是挂了。这时架构师只能采用重启策略。你没看错,就是重启大法。说起来真的很惭愧,但当时真的是只能这样了。
调度中心重启后,花了1万到2万元又挂了。只能重新开始。来回20多次,像挤牙膏一样。而随着开票期限的临近,这种精神上的紧张和恐惧也变得更加强烈。最后,经过1个小时的手动重启,消息终于被消费了。
当时刚好在看毕轩的《分布式Java应用基础与实践》。想是不是线程被阻塞了,于是用Jstack命令查看堆栈状态。果然不出所料,线程阻塞在提交数据的方法上。
我们第一时间与DBA沟通,发现oracle数据库执行了很多大事务,每个大事务执行需要30多分钟,导致调度中心的调度票线程阻塞。
技术部门后来采用了以下方案来避免堆积问题:
生产者发送消息时,将超大消息拆分成多批消息,降低调度中心执行大事务的概率;数据源配置参数,如果事务执行超过一定时间,则自动抛出异常并回滚。1.4 回顾
Spring封装的ActiveMQ API非常简单易用,用起来真的很舒服。
受限于当时彩票技术团队的技术水平和眼界,我们在使用ActiveMQ的过程中遇到了一些问题。
高吞吐量,当消息累积到一定数量时很容易hold
技术团队发现,在吞吐量特别高的场景下,如果消息的堆积越大,ActiveMQ Hanging的几率就越低。
票务网关消息量很大,有些消息不需要立即消费,但是为了避免消息队列Hang的问题,票务网关在消费数据时,先将消息持久化到本地磁盘,生成本地 XML 文件,然后异步和周期性地执行消息。这样,我们大大提高了票务网关的消费速度,基本消除了票务网关排队的堆积。
但是这个方法感觉很奇怪。消费新闻时,必须在本地存储另一份数据。新闻存储在本地。如果磁盘出现故障,也有丢失消息的风险。
高可用机制有待完善
我们采用master/slave部署方式,一主一从,服务器配置为4核8G。
这种部署方式可以同时运行两个ActiveMQ,并且只允许一个slave连接Master,也就是说一个集群只能有2个MQ,两个服务之间有数据备份通道. 单向数据备份。该方案在实际生产线上使用不便,因为当Master挂掉后,Slave无法自动接收Client发送的邀请,需要人工干预,必须先停止Slave再重启恢复负载集群。
还有一些非常奇怪的消息丢失事件。producer发送消息成功,但是master控制台查询不到,但是slave控制台确实可以查询到消息。
但是消费者没有办法消费slave上的消息,只能手动处理。
2 进阶Redis&RabbitMQ
2014年在艺龙网从事红包系统和优惠券系统的优化工作。
2.1 Redis可以做消息队列吗?
酒店优惠券计算服务采用第一代流式计算框架Storm。Storm这里就不详细介绍了,可以参考下面的逻辑图:
这里我们Storm集群的水源(数据源)是redis集群,使用list数据结构实现消息队列的push/pop功能。
流式计算的整体流程:
酒店信息服务向Redis集群A/B发送酒店信息;Storm的spout组件从Redis集群A/B获取数据,获取成功后发送tuple消息给Bolt组件;数据被清理;最后,Storm将处理后的数据发送到Redis集群C;存储服务从Redis集群C获取数据,存储到数据库中;搜索团队扫描数据库表并生成索引。
风暴的描述
这个流计算服务每天处理数千万条数据,处理起来比较流畅。但该计划在团队内部仍有不同的声音:
我认为使用Redis作为消息队列应该满足以下条件:
容忍小概率消息丢失,通过定时任务/手动触发实现最终一致的业务场景;消息堆积概率低,有相关告警监控;消费者的消费模式应该足够简单。2.2 RabbitMQ 是管道而不是池
" />
RabbitMQ 是用 erlang 语言编写的。RabbitMQ 满足了我的两个需求:
高可用性机制。艺龙内部采用的是镜像高可用模式,这种模式在艺龙内部已经使用了很长时间,其稳定性也得到了一定程度的验证。在我负责的红包系统中,RabbitMQ的日吞吐量在百万条消息左右,消息的发送和消费都相当完善。
优惠券服务最初使用的是SqlServer。由于数据量大,技术团队决定采用分库分表的策略,使用公司自研的分布式数据库DDA。
因为是第一次使用分布式数据库,为了测试DDA的稳定性,我们模拟发送1000万条消息到RabbitMQ,然后优惠券重构服务消费消息后,根据hash到不同的mysql库用户号码。
RabbitMQ集群模式是镜像高可用,3台服务器,每台配置4核8G。
我们以每小时 300 万条消息的速度发送消息。第一个小时生产者和消费者的表现都很好,但是由于消费者的速度跟不上生产者的速度,消息队列出现了积压。第三个小时,消息队列已经积累了超过500万条消息,生产者发送消息的速度从最初的2毫秒提升到500毫秒左右。RabbitMQ的控制台当场有血溅,红标告警。
这是一个无意的测试。从测试情况来看,RabbitMQ是优秀的,但是RabbitMQ对消息堆积的支持不是很好。当大量消息积压时,RabbitMQ的性能会急剧下降。
有朋友跟我说:“RabbitMQ明明是个管道,你非要把他当成池子吗?”
随着整个互联网数据量的快速增长,在很多业务场景中允许适当的积累,只要消费者消费顺畅,整个业务波动不大。
我心里越来越相信:消息队列既可以作为管道,也可以作为池。
3 升华 MetaQ
Metamorphosis的由来是我从学习linkedin的开源MQ开始的——现在转入apache的kafka。这是一个设计独特的MQ系统。它使用拉机制而不是一般的 MQ 推模型。它大量使用Zookeeper做服务发现和偏移量存储。我很欣赏也很认同它的设计理念。我强烈建议您阅读它的设计文档。总的来说,蜕变的设计是完全符合它的。---庄晓丹,MetaQ作者
3.1 惊人的消费模式
2015年主要从事中国专用车订单的研发工作。
MetaQ满足了我对消息队列的幻想:“分布式、高吞吐、高积累”。
MetaQ支持两种消费模型:集群消费和广播消费,因为之前使用的消费模型都是使用队列模型。刚开始接触这种发布-订阅模式的时候,我还是很惊叹的。
集群消费
订单创建成功后,发送消息给MetaQ。此消息可由调度服务或 BI 服务使用。
广播消费
当调度服务将订单分配给司机时,它会向司机发送一条推送消息。推送是使用广播消费的方式实现的。
一般过程是:
驱动端的推送服务是一个TCP服务。启动后,以广播方式消费MetaQ的PushTopic;驱动端会定时向推送服务发送TCP请求。认证成功后,推送服务会保存司机号和通道的引用;单服务向MetaQ发送推送消息;推送服务的每台机器都会收到消息,然后判断内存中是否有驱动程序的通道引用,如果有则推送消息。
这是一个非常经典的广播消费案例。我曾经研究过京麦TCP网关的设计,它的推送也是类似的方式。
3.2 积极削峰
2015年是*敏*感*词*大战硝烟弥漫的一年。
就神州专车而言,随着订单的不断增长,业绩压力与日俱增。早晚高峰时段,用户打车时,往往点击下单,往往没有反应。在系统层面,私家车API网关发现大范围超时,订单*敏*感*词*能急剧下降。数据库层面的压力就更大了,高峰期插入一条记录需要8秒。
整个技术团队需要尽快提升私家车系统的性能,之前已经按照模块字段拆分了数据库。但是系统的瓶颈还是很明显的。
我们设计了现在看起来有点激进的东西:
设计订单缓存。如果大家对缓存的方案感兴趣,我们以后再说,有很多点可以详细讨论;在订单的生命周期中,订单的修改操作首先修改缓存,然后发送消息给MetaQ,下单服务消费消息,判断订单信息是否正常(如是否乱序), 如果订单数据是正确的,它将被存储在数据库中。
这里有两个细节:
消费者消费时,需要顺序消费。实现方式是根据订单号路由到不同分区。相同序号的消息每次发送到同一个分区;
一个守护任务,定时轮询当前顺序,当缓存与数据不一致时,修复数据,并发出告警。
本次优化大大提升了订单服务的整体性能,也为后续的订单服务分库分表、异构化打下了坚实的基础。根据我们的统计数据,缓存和数据库之间基本没有最后的不一致。但是这个方案对缓存的高可用要求比较高,有点激进。
3.3 消息SDK包
做过基础架构的同学可能会有这样的体会:“三方组件都会封装一层”,中国架构团队也将metaq-client封装在一层。
在我看来,封装一层可以减少研发人员使用第三方组件的心智投入,统一技术栈,仅此而已。
直到一场意外发生,我的思维升级了。那是一个下午,整个乘车服务崩溃了很长一段时间。技术团队发现:“专车使用zookeeper进行服务发现,zk集群的leader机器挂了,一直在选举leader。”
经过临时解决,我们发现MetaQ和服务发现都使用了同一套zk集群,消费者的offset提交和负载均衡都会对zk集群进行大量的写操作。
为了减少MetaQ对zk集群的影响,我们的目标是:“MetaQ使用独立的zk集群”。
需要部署一个新的zk集群;MetaQ的zk数据需要同步到新集群;保证切换到新集群,应用服务基本无感知。
好奇的问了建筑系的同学。他说新集群已经部署好了,但是zk数据需要同步到新集群。他在客户端添加了双写操作。也就是说:除了在原来的zk集群中写一份数据,我们还要在新的zk集群中写一份数据。几周后,MetaQ 使用单独的 zk 集群的任务已经完成。
这次经历给我带来了很多感慨:“我还能这样玩吗?” 这也让我想到:三方组件的封装并没有想象的那么简单。
我们可以看看快手消息的SDK打包策略:
对外只提供了最基本的API,所有访问都必须通过SDK提供的接口。简洁的 API 就像冰山一角。除了简单的外部接口外,以下所有内容都可以在不破坏兼容性的情况下进行升级和替换;业务开发也很简单,只要提供Topic(全局唯一)和Group即可生产和消费,无需提供环境、NameServer地址等。在SDK内部,会根据需要解析集群NameServer的地址到主题,然后连接到相应的集群。生产环境和测试环境会解析不同的地址,从而实现隔离;上图分为3层,第二层一般,第三层对应具体的MQ实现。因此理论上可以用其他Message中间件替代,客户端程序不需要修改;SDK集成了热改机制,可以在不重启Client的情况下动态配置,比如下发路由策略(更换集群NameServer的地址,或者连接到另一个集群Go),Client的线程数,超时时间期等。通过Maven的强制更新机制,可以保证业务使用的SDK基本是最新的。
3.4 重构MetaQ,形成自成一体的系统
我有一个习惯:“我经常找运维、DBA、架构师,了解当前系统有没有问题,以及他们解决问题的思路,这样我就有了另一个角度来审视运维公司系统。”
MetaQ也有他的缺点。
MetaQ的基础通信框架是gecko,MetaQ偶尔会出现rpc无响应,应用卡顿的情况,不易定位问题;MetaQ的运维能力较弱,只有简单的Dashboard界面,无法实现自动主题申请、消息追踪等功能。
有一天,我发现测试环境的一台消费者服务器启动后,一直报链接异常,CPU占用率高。我立即用 netstat 命令查看,发现已经创建了数百个链接。出于好奇,打开源码,发现网络通信框架gecko已经被netty取代了。我们会第一时间联系建筑系的同学。
那时我才意识到:他们已经开始重构 MetaQ。我从来没有想过重构一个开源软件,因为它离我太远了。或者那个时候觉得自己能力不行。
后来中国自研的消息队列成为了自己的系统,在生产环境中一直运行的很好。
时至今日,我仍然很佩服中国建筑团队。他们自己开发了消息队列、DataLink(数据异构中间件)、分库分表中间件等。他们乐于创新,勇于做出更好的技术产品。
我从他们身上学到了很多。
" />
可能是看到他们重构MetaQ的那一刻,心里就种下了一颗*敏*感*词*。
4 热爱RocketMQ4.1开源盛宴
2014年的时候,搜了很多关于淘宝消息队列的资料。我知道MetaQ的版本已经升级到MetaQ 3.0,但是开源版本还没有发布。
大约在秋天,我加入了 RocketMQ 技术组。石佳(RocketMQ创始人)在群里说:“最近开源要发布了,发布了大家抓紧fork一下。” 他这句话发到群里后,群里炸开了锅。心里更加高兴了,期待早日看到阿里自己的内部消息中间件。
最后,RocketMQ终于开源了。我迫不及待地想看他一眼。
因为想学网络编程,而RocketMQ的通讯模块remoting底层也是Netty写的。因此,RocketMQ的通信层是我学习的起点。
我模仿了RocketMQ的remoting,写了一个玩具rpc,大大提升了自信心。巧合的是,艺龙举办了科技创新活动。我想了想,不如试试用Netty重写Cobar的通信模块。于是参考Cobar的源码,花了两周的时间写了一个netty版的proxy,其实很粗糙,很*敏*感*词*还不完善。后来这次活动给了我一个鼓励奖,现在想想都觉得有趣。
因为在UCAR中使用了MetaQ,所以我在学习RocketMQ方面也比较得心应手。为了真正理解源码,我经常参考RocketMQ的源码,写一些轮子来验证自己的学习效果。
虽然自己也做过一些练习,但是从来没有在商业环境中使用过。2018年是我真正使用RocketMQ的一年,也是收获的一年。
短信服务
短信服务应用广泛,比如用户注册登录验证码、营销短信、下单成功短信通知等。当初设计短信服务的时候,想了解一下业界是怎么做的。于是目标就锁定在了腾讯云的短信服务上。腾讯云的短信服务具有以下特点:
所以,我参考了这个设计思路。
模仿腾讯云SDK设计,提供简单易用的短信接口;设计短信服务API,接收短信请求,发送短信信息到消息队列;worker服务消费消息,根据负载均衡算法Interface调用不同通道提供者的SMS消息;Dashboard可以查看短信发送记录,配置渠道商信息。
短信服务是我第一次真正意义上在生产环境中使用RocketMQ。当短信一条一条发出去的时候,还是挺有成就感的。
MQ控制台
用过RocketMQ的朋友一定对上图的控制台不陌生。当时团队有多个 RocketMQ 集群,每个集群需要部署一个单独的控制台。所以我想:我能不能稍微修改一下控制台来支持多集群。
所以,我卷起袖子开始工作。在开源版本的基础上修改了可以支持多组集群的版本,用了大概20天。做完之后,虽然能满足我最初的想法,但是很粗糙。而且,搜狐还开源了自己的MQCloud。看了他们的设计,感觉离一个消息管理平台还差得很远。
后来又看了两篇《网易云音乐的消息队列改造之路》和《今日头条在消息服务平台和容灾体系建设中的实践与思考》。我越痒,我就越想做。它是一个真正的消息管理平台。可惜一直没有场景和机会。
最近看了单车架构专家梁勇的一篇《Hello在分布式消息治理和微服务治理方面的实践》,推荐大家阅读。
一个窗口,启动自研组件
后来尝试用RocketMQ更进一步。
这些做完之后,我们就自己开发了注册中心,配置中心,任务调度系统。在设计这些系统的时候,我从RocketMQ的源码中汲取了很多营养。虽然看起来设计上还有很多不完善的地方,代码质量也有待提高,但是在做完这些系统之后,我的自信心得到了很大的提升。
RocketMQ为我打开了一扇窗,让我看到了更广阔的Java世界。对我来说,这是开源的盛宴。
4.2 Kafka:大数据生态不可或缺的一部分
Kafka是一个分布式消息流处理中间件,具有高吞吐、持久、水平可扩展、支持流式数据处理等特点。、在线/离线系统分析、实时监控等领域有着广泛的应用。
日志同步
在大型业务系统设计中,为了快速定位问题,全链路跟踪日志,及时监控故障,通常需要对各个系统应用的日志进行集中分析处理。
Kafka设计的初衷是为了应对大量的日志传输场景。应用程序将日志消息以可靠和异步的方式同步到消息服务,然后使用其他组件实时或离线分析日志。它还可以用于采集
关键日志信息以进行应用程序监控。
日志同步主要有三个关键部分:日志采集客户端、Kafka消息队列、后端日志处理应用。
日志采集客户端负责用户各种应用服务的日志数据采集,将日志以消息的形式“批量”、“异步”发送给Kafka客户端。Kafka客户端批量提交和压缩消息,对应用服务的性能影响很小。Kafka 将日志存储在消息文件中以提供持久性。一个日志处理应用程序,如Logstash,在Kafka中订阅和消费日志消息,最后提供文件搜索服务来检索日志,或者Kafka将消息传递给其他大数据应用程序,如Hadoop进行系统存储和分析。
日志同步*敏*感*词*:
流计算处理
在股市走势分析、气象数据测控、网站用户行为分析等诸多领域,由于数据生成速度快、实时性强、体量大,很难统一采集这些数据并进行分析。加工前将它们存放在仓库中。因此,传统的数据处理架构无法满足需求。Kafka、Storm、Samza、Spark等流计算引擎的出现,就是为了更好的解决这类数据处理过程中遇到的问题。流计算模型可以在数据流动过程中实现对数据的实时捕获和处理。处理,并根据业务需求进行计算分析,最后将结果保存或分发到需要的组件中。
数据传输中心
近10年来,KV存储(HBase)、搜索(ElasticSearch)、流处理(Storm、Spark、Samza)、时序数据库(OpenTSDB)等专用系统应运而生。这些系统诞生时心中只有一个目标,因为它们的简单性使得在商品硬件上构建分布式系统变得更加容易和更具成本效益。通常,需要将相同的数据集注入多个专用系统。例如,当应用日志用于离线日志分析时,搜索单独的日志记录也是必不可少的,建立独立的工作流来采集
每一类数据,然后将它们导入到自己的专用系统中显然是不切实际的。使用消息队列 Kafka 版本充当数据传输中心,
下图是美团MySQL数据实时同步到Hive的架构图,也是一个非常经典的案例。
4.3 如何选择技术
2018年去哪儿QMQ开源,2019年腾讯TubeMQ开源,2020年Pulsar如火如荼。
消息队列的生态如此繁荣,那么我们该如何选择模型呢?
我认为我们不必局限于消息队列,我们可以扩展它。只是谈谈我的看法。
数据库正在专业化——“一刀切”的方法不再适用 ----- MongoDB 设计哲学
第一点:先有场景,再有适应这个场景的技术。什么样的场景选择什么样的技术。
第二点:现实往往很复杂。当我们真正进行技术选型并需要实施时,技术储备和成本是我们需要重点关注的两个因素。
技术储备
成本
最后一点是人的因素,尤其是管理者的因素。每一次重大的技术选型,都考验着技术管理者的眼光、布局和管理智慧。
5 写到最后
我觉得这个世界上没有不合理的事情。真的,没有多多的积累,多多的思考,是做不成事情的。. . 总之,体验了这部电影,感觉自己要学习的东西太多了。这个世界上有能力的人太多了。你认为的极限,如果没有做好,只是别人的起点。所以唯有不断进取,才能不丢人。好吧,人们不必上学,但他们必须学习,真的。------韩寒《未来永无止境》演讲
我学习消息队列的过程就是一个不断思考和实践的过程。虽然我觉得极限不好,只是别人的起点,但至少现在,当我面对这个技术的时候,我的内心充满了好奇。心亦无惧。
我始终相信:每天学一点,就是比昨天好一点。
微信8.0让好友达到10000,好友可以加我plus size,先到先得,过后就没了
扫描下方二维码加我微信,2022,抱在一起取暖,一起帅。
案例研究:强化学习如何做数据分析?新加坡国立等TKDE 2022综述论文
【新致远简介】数据分析是现在必备的技能之一。传统上,静态算法或规则多用于数据分析,但在现实场景中,往往面临复杂的交互环境,如何学习更好的策略是一个非常现实的问题。幸运的是,强化学习可以作为解决此类问题的有效方法。新加坡南洋理工大学的学者在 TKDE 发表了一篇关于“深度强化学习数据处理和分析”的综述论文,全面回顾了近期的工作,重点是使用 DRL 改进数据处理和分析。
数据处理和分析是基础和普遍的。算法在数据处理和分析中起着至关重要的作用,许多算法设计结合了人类知识和经验的启发式和一般规则以提高其有效性。
近年来,强化学习,尤其是深度强化学习(DRL)在许多领域得到了越来越多的探索和利用,因为与静态设计的算法相比,它可以在复杂的交互环境中学习到更好的策略。在这种趋势的推动下,我们对最近的工作进行了全面回顾,重点是使用 DRL 改进数据处理和分析。
首先,我们介绍 DRL 中的关键概念、理论和方法。接下来,我们将讨论DRL在数据库系统上的部署,以方便数据组织、调度、调优和索引等各个方面的数据处理和分析。
然后,我们研究 DRL 在数据处理和分析中的应用,从数据准备和自然语言处理到医疗保健、金融科技等。
最后,我们讨论了在数据处理和分析中使用 DRL 的重要挑战和未来的研究方向。
论文链接:
在大数据时代,数据处理和分析是基本的、无处不在的,对于许多正在数字化旅程中改善和转变其业务和运营的组织来说至关重要。数据分析通常需要其他关键操作,例如数据采集、数据清理、数据集成、建模等,然后才能提取见解。
从医疗保健到零售,大数据可以在许多行业释放巨大的价值创造。然而,数据的复杂性(例如,大容量、高速度和高多样性)对数据分析提出了许多挑战,使其难以获得有意义的见解。为了迎接这一挑战,促进高效、有效的数据处理和分析,研究人员和从业者设计了大量的算法和技术,也开发了大量的学习系统,如Spark MLlib和Rafiki。
为了支持快速的数据处理和准确的数据分析,大量算法依赖于基于人类知识和经验制定的规则。例如,“最短作业优先”是一种调度算法,选择执行时间最短的作业进行下一次执行。但与没有充分利用工作负载特性的基于学习的调度算法相比,其性能较差。另一个例子是计算机网络中的数据包分类,它将数据包与一组规则中的一个相匹配。一种解决方案是使用手动调整的分类启发式方法来构建决策树。具体来说,启发式算法是为一组特定的规则而设计的,因此可能不适用于具有不同特征的其他工作负载。
" />
我们观察到现有算法的三个局限性:
首先,该算法是次优的。规则可能会忽略或未充分利用数据分布等有用信息。其次,该算法缺乏自适应能力。为特定工作负载设计的算法在不同的工作负载中表现不佳。第三,算法设计是一个耗时的过程。开发人员必须花费大量时间尝试许多规则才能找到一个凭经验行得通的规则。
基于学习的算法也用于数据处理和分析。常用的学习方法有两种:监督学习和强化学习。他们通过直接优化性能目标来实现更好的性能。监督学习通常需要一组丰富的高质量带注释的训练数据,而获取这些数据既困难又具有挑战性。例如,配置调整对于优化数据库管理系统 (DBMS) 的整体性能非常重要。在离散和连续空间中可能有数百个相互关联的调谐旋钮。此外,不同的数据库实例、查询工作负载和硬件特性使得数据采集
不可用,尤其是在云环境中。
强化学习比监督学习具有更好的性能,因为它采用试错法搜索并且需要更少的训练样本来为云数据库找到良好的配置。
另一个具体的例子是查询处理中的查询优化。数据库系统优化器的任务是为查询找到最佳的执行计划,以降低查询成本。传统的优化器通常会枚举许多候选计划并使用成本模型来找到成本最低的计划。优化过程可能缓慢且不准确。
在不依赖不准确的成本模型的情况下,深度强化学习 (DRL) 方法通过与数据库交互(例如,更改表连接顺序)来改进执行计划。
当查询被发送到代理(即 DRL 优化器)时,代理通过表征基本信息(例如访问的关系和表)来生成状态向量。代理将状态作为输入,并使用神经网络生成一个动作集的概率分布,其中可以收录
所有可能的连接操作作为潜在动作。
每个操作代表一对表的部分连接计划,一旦执行操作,状态就会更新。在采取可能的行动之后,生成一个完整的计划,然后由 DBMS 执行以获得奖励。
在这个查询优化问题中,可以根据实际延迟计算奖励。在使用奖励信号进行训练期间,代理可以改进其策略,从而产生更好的连接顺序(即更少的延迟)和更高的奖励。
用于查询优化的 DRL 工作流
强化学习 (RL) 侧重于学习在环境中智能地行动。RL 算法通过基于探索和开发的环境反馈来改进自身。在过去的几十年里,强化学习在理论和技术上都取得了长足的进步。
" />
值得注意的是,DRL 结合了深度学习 (DL) 技术来处理复杂的非结构化数据,旨在从历史数据中学习和自我探索,以解决众所周知的困难和*敏*感*词*问题(例如 AlphaGo)。
近年来,来自不同社区的研究人员提出了 DRL 解决方案,以解决数据处理和分析中的问题。我们从系统和应用程序的角度使用 DRL 对现有作品进行分类。
从系统的角度来看,我们专注于基础研究主题,从一般的(例如调度)到特定于系统的(例如数据库查询优化)。我们还应该强调它是如何被表述为马尔可夫决策过程的,并讨论与传统方法相比如何更有效地解决 DRL 问题。由于实际系统中的工作负载执行和数据获取时间比较长,因此采用采样、模拟等技术来提高DRL训练的效率。
从应用的角度,我们将涵盖数据处理和数据分析中的各种关键应用,以全面了解 DRL 的可用性和适应性。许多领域通过采用 DRL 进行转换,这有助于学习有关应用程序的特定领域知识。
在这篇综述中,我们旨在对使用深度强化学习解决数据系统、数据处理和分析问题的最新进展进行广泛而系统的综述。
强化学习技术分类
参考:
[1] J. Manyika、M. Chui、B. Brown、J. Bughin、R. Dobbs、C. Roxburgh、A. Hung Byers 等,大数据:创新、竞争和生产力的下一个前沿。麦肯锡全球研究院,2011 年。
[2] X. Meng、J. Bradley、B. Yavuz、E. Sparks、S. Venkataraman、D. Liu、J. Freeman、D. Tsai、M. Amde、S. Owen 等人,“Mllib:机器在 apache spark 中学习,”机器学习研究杂志,卷。17,没有。1,第 1235–1241 页,2016 年。
[3] W.Wang、J. Gao、M. Zhang、S.Wang、G. Chen、TK Ng、BC Ooi、J. Shao 和 M. Reyad,“Rafiki:机器学习作为分析服务系统”, VLDB,卷。12,没有。2,第 128–140 页,2018 年。