分布式开放消息网(RocketMQ)的规律及实践

作者:July
起处于:结构的法算法之道blog

相同年前为一蹩脚中分享而写的即首文章,没悟出会发生如此多口阅览,抽空更新一版本,对文中部分涩的言语做了修正,删除了有口水话和附录内容,尽量给大家还好之读书体验
(第二版本更新为2017年春节)。

 

分布式消息网作为贯彻分布式系统可扩大、可伸缩性的要害组件,需要所有高吞吐量、高可用抵特性。而说到消息网的宏图,就逃不了少单问题:

前言

  
一般而言,标题含有“秒杀”,“99%”,“史上无限咸/最强”等词汇的反复还免去不了哗众取宠之嫌,但进一步来讲,如果读者读了此文,却任凭任何获,那么,我哉愿意承受这样的罪行,:-),同时,此文可以视作是针对立即首文章:十道海量数据处理面试题和十独主意好总结的一般抽象性总结。

   
毕竟给文章和驳斥的限,本文将摒弃绝大部分之细节,只提艺术/模式论,且珍惜用最为浅最直白的语言阐述相关题材。最后,有好几不能不强调的凡,全文行文是冲对试题的剖析基础之上的,具体实行过程被,还是得具体情况具体分析,且场景为颇为较本文所陈述之外一样种植状况复杂得差不多。

    OK,若有另问题,欢迎随时不吝赐教。谢谢。

  1. 消息的各个问题
  2. 信息之又问题

叫海量数据处理?

  
所谓海量数据处理,无非就是是依据海量数据上的储存、处理、操作。何谓海量,就是数据量太要命,所以造成要么是力不从心在比短日外高速解决,要么是多少最怪,导致力不从心一次性装入内存。

   
那解决办法呢?针对时,我们得以动用巧妙的算法搭配合适的数据结构,如Bloom
filter/Hash/bit-map/堆/数据库或倒排索引/trie树,针对空中,无非就是一个艺术:大如化小:分而治之/hash映射,你无是说规模最好嘛,那简单啊,就管范围大化为面小之,各个击破不纵结束了呗。

   
至于所谓的单机及集群问题,通俗点来讲,单机就是拍卖装数据的机有限(只要考虑cpu,内存,硬盘的数量交互),而集群,机器来差不多部,适合分布式处理,并行计算(更多考虑节点和节点内的数额交互)。

    再者,通过本blog内的关于海量数据处理的稿子:Big Data
Processing,我们都盖了解,处理海量数据问题,无非就是是:

 

  1. 分而治之/hash映射 + hash统计 + 堆/快速/归并排序;
  2. 双层桶划分
  3. Bloom filter/Bitmap;
  4. Trie树/数据库/倒排索引;
  5. 外排序;
  6. 分布式处理之Hadoop/Mapreduce。

   
下面,本文第一组成部分、从set/map谈到hashtable/hash_map/hash_set,简要介绍下set/map/multiset/multimap,及hash_set/hash_map/hash_multiset/hash_multimap之分(万丈高楼平地起,基础太要),而本文第二片,则对上述那6种艺术模式做对应之雅量数据处理面试题分别实际阐述。

 

RocketMQ作为阿里开源的一律款款大性能、高吞吐量的消息中间件,它是何等来缓解当时简单只问题之?RocketMQ
有怎么样主要特性?其落实原理是如何的?

首先部分、从set/map谈到hashtable/hash_map/hash_set

   
稍后本文第二有的中将多次事关hash_map/hash_set,下面小有些介绍下这些器皿,以当基础准备。一般的话,STL容器分点儿种植,

  • 序列式容器(vector/list/deque/stack/queue/heap),
  • 关联式容器。关联式容器又分为set(集合)和map(映射表)两万分接近,以及马上简单不胜类的衍生体multiset(多键集合)和multimap(多键映射表),这些器皿都以RB-tree完成。此外,还有第3像样关联式容器,如hashtable(散列表),以及以hashtable为根机制好的hash_set(散列集合)/hash_map(散列映射表)/hash_multiset(散列多键集合)/hash_multimap(散列多键映射表)。也就是说,set/map/multiset/multimap都内含一个RB-tree,而hash_set/hash_map/hash_multiset/hash_multimap都内含一个hashtable。

   
所谓关联式容器,类似关联式数据库,每笔数据还是每个元素还有一个键值(key)和一个实值(value),即所谓的Key-Value(键-值对)。当元素让插入到关联式容器被时,容器内部结构(RB-tree/hashtable)便随其键值大小,以某种特定规则以之因素放置于方便位置。

   
 比如,在MongoDB中,文档(document)是太中心的数据组织形式,每个文档以Key-Value(键-值对)的主意组织起。一个文档可以发差不多单Key-Value组合,每个Value可以是殊的种,比如String、Integer、List等等。 
{ “name” : “July”,  
   “sex” : “male”,  
   “age” : 23 }  

 

set/map/multiset/multimap

   
set,同map一样,所有因素还见面基于元素的键值自动为排序,因为set/map两者的拥有各种操作,都止是反而调用RB-tree的操作行为,不过,值得注意的是,两者都无同意两独元素来雷同之键值。
   
不同之是:set的素不像map那样可以而且拥有实值(value)和键值(key),set元素的键值就是实值,实值就是键值,而map的兼具因素都是pair,同时负有实值(value)和键值(key),pair的首先只因素被视为键值,第二独要素让视为实值。
   
至于multiset/multimap,他们之表征以及用法及set/map完全相同,唯一的出入就在它允许键值重复,即享的插操作基于RB-tree的insert_equal()而非insert_unique()。

hash_set/hash_map/hash_multiset/hash_multimap

   
hash_set/hash_map,两者的整套操作都是基于hashtable之上。不同的凡,hash_set同set一样,同时所有实值和键值,且实质就是是键值,键值就是实值,而hash_map同map一样,每一个元素以兼有一个实值(value)和一个键值(key),所以其以办法,和地方的map基本相同。但由hash_set/hash_map都是冲hashtable之上,所以未备自动排序功能。为什么?因为hashtable没有电动排序功能。
   
至于hash_multiset/hash_multimap的性状以及地方的multiset/multimap完全相同,唯一的异样就是她的根实现机制是hashtable,所以它们的素都未会见吃自动排序,不过为还兴键值重复。

   
所以,综上,说白了,什么样的结构决定其安的属性,因为set/map/multiset/multimap都是冲RB-tree之上,所以有全自动排序功能,而hash_set/hash_map/hash_multiset/hash_multimap都是依据hashtable之上,所以无带有自动排序功能,至于加个前缀multi_偏偏就是是许键值重复而已。

   
此外,关于什么hash,请圈这首文章:http://blog.csdn.net/v\_JULY\_v/article/details/6256463;关于瑞黑树,请参看blog内密密麻麻文章:http://blog.csdn.net/v\_july\_v/article/category/774945,关于hash_map的现实性应用,可看这首文章:http://blog.csdn.net/sdhongjun/article/details/4517325。

    OK,接下去,请看本文第二有些、处理海量数据问题之六管密匙。

 

关键特性和那个实现原理

其次局部、处理海量数据问题之六将密匙

同样、顺序信

消息有序指的凡好按信息的殡葬顺序来消费。例如:一画订单有了 3
修信息,分别是订单创建、订单会、订单完成。消费时,要遵循顺序依次消费才出义。与此同时多画订单中以是足以彼此消费的。首先来拘禁如下示例:

假如生产者产生了2条消息:M1、M2,要管这片久消息的依次,应该怎么样做?你脑子中想到的也许是如此:

你也许会见以这种方法确保信息顺序

假定M1发送至S1,M2发送至S2,如果要是保管M1先被M2被消费,那么要M1到达消费端被消费后,通知S2,然后S2再将M2发送到消费端。

夫模型是的问题是,如果M1和M2分别发送至个别宝Server上,就未克保证M1先上MQ集群,也非能够确保M1被先行花。换个角度看,如果M2先于M1达到MQ集群,甚至M2被消费后,M1才达到消费端,这时消息呢尽管混序了,说明上述模型是勿可知担保信息的顺序的。如何才会以MQ集群保证信息的逐一?一种简易的措施就是用M1、M2发送到与一个Server上:

管信息顺序,你改善后的方式

诸如此类好确保M1先让M2到达MQServer(生产者等M1发送成功后重新发送M2),根据先上先给消费之准绳,M1会早早M2被消费,这样虽管了信息之逐条。

此模型也特是辩论及足管信息的相继,在实际状况中或者会见碰到下面的问题:

网延迟问题

倘若以信息于平令服务器发于外一样大服务器,就会有网络延迟问题。如齐图所示,如果发送M1耗时过量发送M2的耗时,那么M2就按用吃优先花,仍然不能够担保信息之逐条。即使M1和M2同时抵达消费端,由于不晓消费端1和花端2的负载情况,仍然有或出现M2先于M1被消费的事态。

那么如何化解这题目?将M1和M2发于和一个消费者,且发送M1后,需要消费端响应成功后才会发送M2。

聪慧之您恐怕已想到另外的问题:如果M1被发送至消费端后,消费端1没有响应,那是持续发送M2呢,还是再次发送M1?一般为保信息一定叫消费,肯定会选择重发M1到另外一个花端2,就设下图所著。

确保信息顺序的正确姿势

如此的模型就严格保证信息之次第,细心之君还会发现题目,消费端1没有响应Server时有三三两两栽情况,一栽是M1确实没有到达(数据以网络传送着丢掉),另外一栽消费端已经消费M1且一度发送响应消息,只是MQ
Server端没有接过。如果是次种情况,重发M1,就会见招致M1被重新消费。也即引入了咱们如果说的老二个问题,消息再度问题,这个后文会详细讲解。

回过头来看信顺序问题,严格的逐条消息非常容易理解,也可以透过文中所讲述的主意来概括处理。总结起来,要实现严格的相继消息,简单且使得之章程尽管是:

保证生产者 - MQServer - 消费者是平等对准一定底涉嫌

然的统筹虽简易易行,但也会存在部分特别要紧的问题,比如:

  1. 并行度就会见化为信息网的瓶颈(吞吐量不够)
  2. 再多的杀处理,比如:只要消费端出现问题,就会招整个拍卖流程阻塞,我们只好花费还多的生机来化解阻塞的问题。

可我们的最终目标是要集群的高容错性和赛吞吐量。这不啻是一模一样对准不可调和的矛盾,那么阿里是哪些化解的?

世界上解决一个计算机问题最简便的不二法门:“恰好”不欲解决其!——
沈询

稍许问题,看起很要紧,但实际上我们得经客观之宏图或者拿题目解释来逃避。如果硬而将工夫花在化解问题本身,实际上不仅效率低下,而且也是千篇一律栽浪费。从夫角度来拘禁信之一一问题,我们可以得出两独结论:

  1. 莫关心乱序的应用实际大量有
  2. 队无序并无表示消息无序

故此于事情规模来保证信息之逐一而不仅是指让信息网,是不是我们当寻求的同等种更合理之法门?

末尾我们从源码角度解析RocketMQ怎么落实殡葬顺序消息。

RocketMQ通过轮询所有班的措施来规定消息于发送至啦一个班(负载均衡策略)。比如下面的以身作则中,订单号一样的信会为先后发送至跟一个行列中:

// RocketMQ通过MessageQueueSelector中实现的算法来确定消息发送到哪一个队列上
// RocketMQ默认提供了两种MessageQueueSelector实现:随机/Hash
// 当然你可以根据业务实现自己的MessageQueueSelector来决定消息按照何种策略发送到消息队列中
SendResult sendResult = producer.send(msg, new MessageQueueSelector() {
    @Override
    public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
        Integer id = (Integer) arg;
        int index = id % mqs.size();
        return mqs.get(index);
    }
}, orderId);

以博到程由于信息后,会根据MessageQueueSelector兑现之算法来选择一个班,同一个OrderId获取到的早晚是跟一个队。

private SendResult send()  {
    // 获取topic路由信息
    TopicPublishInfo topicPublishInfo = this.tryToFindTopicPublishInfo(msg.getTopic());
    if (topicPublishInfo != null && topicPublishInfo.ok()) {
        MessageQueue mq = null;
        // 根据我们的算法,选择一个发送队列
        // 这里的arg = orderId
        mq = selector.select(topicPublishInfo.getMessageQueueList(), msg, arg);
        if (mq != null) {
            return this.sendKernelImpl(msg, mq, communicationMode, sendCallback, timeout);
        }
    }
}

密匙一、分而治之/Hash映射 + Hash统计 + 堆/快速/归并排序

1、海量日志数据,提取出某日访问百度次数最多的良IP。

   
既然是海量数据处理,那么可想而知,给咱的数目那就是肯定是海量的。针对是数额的雅量,我们如何入手呢?对的,无非就是是分而治之/hash映射

  • hash统计 + 堆/快速/归并排序,说白了,就是先映射,而后统计,最后排序:

  • 分而治之/hash映射:针对数据极其可怜,内存受限,只能是:把万分文件化成(取模映射)小文件,即16配方针:大如化小,各个击破,缩小规模,逐个解决

  • hash统计:当好文件转发了略微文件,那么我们就是好动用常规的hash_map(ip,value)来进行频率统计。
  • 堆/快速排序:统计截止了下,便进行排序(可采取堆排序),得到次数最多的IP。

   具体而论,则是:
“首先是即刻无异于天,并且是访问百度的日志被的IP取出来,逐个写副到一个老大文件被。注意到IP是32位之,最多有个2^32只IP。同样好下映射的主意,比如模1000,把全大文件映射为1000单稍文件,再寻觅来每个微文中出现频率最要命的IP(可以利用hash_map进行频率统计,然后重新寻觅来效率最酷的几乎独)及相应的效率。然后又以马上1000单极充分的IP中,找来好频率最要命之IP,即为所要。”–十鸣海量数据处理面试题和十单艺术充分总结。

   
注:Hash取模是同样种等价映射,不见面有与一个要素分散到不同小文件被去的情况,即这里用的是mod1000算法,那么等同的IP在hash后,只或赢得于同一个文件被,不容许让疏散的。

   
那究竟什么是hash映射呢?我换个角度举个浅显直白的例证,如本文的URL是:http://blog.csdn.net/v\_july\_v/article/details/7382693,当自己把这URL发表于微博高达,便受射成了:http://t.cn/zOixljh,于斯,我们发现URL本身的长为缩短了,但马上半独URL对应的篇章的是同等篇就本文。OK,有趣味的,还得更了解下一致性hash算法,见这文第五有的:http://blog.csdn.net/v\_july\_v/article/details/6879101。

2、搜索引擎会通过日记文件把用户每次搜寻使用的兼具寻串都记录下来,每个查询串的长为1-255字节。

   
假设目前产生一千万只记录(这些查询串的重复度比较高,虽然总数是1千万,但只要除去重复后,不跳3百万单。一个查询串的重复度越强,说明查询其的用户更多,也就是是尤为红),请你统计最红的10单查询串,要求利用的内存不可知过1G。

   
由方第1写,我们领略,数据充分则划为多少的,但如果数量规模比较小,能一次性装入内存也?比如就第2开,虽然来一千万个Query,但是由于重复度比较强,因此实际只是发生300万之Query,每个Query255Byte,因此我们得以考虑将她们还放上内存中去,而今天单纯是急需一个适当的数据结构,在此地,Hash
Table绝对是咱们先的选料。所以我们抛开分而治之/hash映射的法子,直接上hash统计,然后排序。So,

  1. hash统计:先对当下批海量数据预处理(维护一个Key为Query字串,Value为该Query出现次数之HashTable,即hash_map(Query,Value),每次读取一个Query,如果该字串不在Table中,那么投入该字串,并且以Value值设为1;如果该字串在Table中,那么将拖欠字串的计数加同即可。最终我们在O(N)的时间复杂度内用Hash表完成了统计;
  2. 堆放排序:第二步、借助堆这个数据结构,找有Top
    K,时间复杂度为N‘logK。即借助堆结构,我们得在log量级的流年内寻找和调整/移动。因此,维护一个K(该问题中凡10)大小的小根堆,然后遍历300万底Query,分别跟根元素进行对比所以,我们最后的时复杂度是:O(N) +
    N’*O(logK),(N为1000万,N’为300万)。

   
别忘了就首文章被所陈述之积聚排序思路:“维护k个元素的绝小堆,即用容量为k的太小堆存储最先遍历到的k个数,并而它们就是无比要命之k个数,建堆费时O(k),并调动堆(费时O(logk))后,有k1>k2>…kmin(kmin设为小顶堆中尽小元素)。继续遍历数排列,每次遍历一个元素x,与堆顶元素于,若x>kmin,则更新堆(用时logk),否则不更新堆。这样下来,总费时O(k*logk+(n-k)*logk)=O(n*logk)。此道得益于在积着,查找等各类操作时间复杂度均为logk。”–其三章续、Top
K算法问题的实现。
   
当然,你吧足以采用trie树,关键字域存该查询串出现的次数,没有出现为0。最后用10只元素的不过小推来对出现频率进行排序。

3、有一个1G高低的一个文书,里面每一样履是一个歌词,词之大大小小非越16字节,内存限制大小是1M。返回频数最高的100只词。
       由方那片只例题,分而治之 + hash统计 +
堆/快速排序这个套路,我们就开始来了屡试不爽的感觉。下面,再用几鸣还多验证下。请圈这第3书写:又是文本充分挺,又是内存受限,咋办?还会怎么收拾也?无非要:

  1. 分而治之/hash映射:顺序读文件被,对于每个词x,取hash(x)%5000,然后照该值存到5000只小文件(记为x0,x1,…x4999)中。这样每个文件约是200k左右。如果内部的片文件超过了1M轻重缓急,还可以类似之道继续于下分,直到分解得到的略文件之大大小小都未越1M。
  2. hash统计:对每个微文件,采用trie树/hash_map等统计每个文件中出现的词和相应的频率。
  3. 堆/归并排序:取出出现频率最可怜的100单词(可以据此带有100只结点的极小堆),并将100独词与相应的效率存入文件,这样又收获了5000单文件。最后就将立即5000只文本进行统一(类似于由并排序)的经过了。

4、海量数据分布在100玉微机被,想个办法高效统计出这批数量的TOP10。

    此题与方第3挥毫类似,

  1. 堆排序:在各个台计算机上求出TOP10,可以应用包含10独元素的积好(TOP10稍,用最为充分堆,TOP10怪,用最小堆)。比如求TOP10怪,我们率先得到前10只因素调整成为最小堆,如果发现,然后扫描后的数据,并和堆顶元素于,如果比堆顶元素大,那么用该因素交替堆顶,然后再次调动为极小堆。最后堆着之素就是TOP10分外。
  2. 请求来每台微机及之TOP10继,然后把及时100华电脑上的TOP10组成起来,共1000只数据,再运方面类似的道要出TOP10纵可以了。

   
上述第4开的是解法,经读者反馈出问题,如举个例如比较要要2只文本被的top2,照你这种算法,如果第一个文件里生

a 49次

b 50次

c 2次

d 1次

    第二单文本里来

a 9次

b 1次

c 11次

d 10次

     虽然第一独文本里下top2是b(50次等),a(49不成),第二只文本里出来top2凡c(11坏),d(10坏),然后2独top2:b(50差)a(49差)与c(11次)d(10次)归并,则算有具有的文本的top2是b(50
次),a(49 次),但实际是a(58 次),b(51
次)。是否算如此呢?若确这样,那作何解决吧?

    正使老梦所述:

   
首先,先管所有的数目遍历一不折不扣开一样蹩脚hash(保证同一的多少条目划分到均等台计算机上进行演算),然后根据hash结果又分布至100贵电脑受到,接下去的算法按照事先的即可。

   
最后由于a可能出现于不同之微处理器,各出肯定的次数,再针对每个相同条目进行求和(由于达同步骤中hash之后,也有利各令微机就待对友好分到的条款内进行求和,不干到别的电脑,规模压缩)。

5、有10独文本,每个文件1G,每个文件之各级一行存放的还是用户的query,每个文件之query都可能还。要求而按照query的频度排序。

   直接上:

  1. hash映射:顺序读取10只公文,按照hash(query)%10底结果以query写副到另外10个文本(记为)中。这样初转变的文件每个的分寸约为1G(假设hash函数是随便的)。
  2. hash统计:找一令内设有2G横的机器,依次对用hash_map(query,
    query_count)来统计每个query出现的次数。注:hash_map(query,query_count)是因此来统计每个query的出现次数,不是储存他们之值,出现一样蹩脚,则count+1。
  3. 堆积如山/快速/归并排序:利用高效/堆/归并排序按照出现次数进行排序。将排序好的query和相应的query_cout输出到文件中。这样得到了10只败好序的文本(记为)。对及时10个文件进行由并排序(内排序和外排序相结合)。

     除此之外,此题还有以下简单独艺术:
   
方案2:一般query的总量是少数的,只是重新的次数比较多设已经,可能对此有的query,一次性就可参加到内存了。这样,我们就可以应用trie树/hash_map等一直来统计每个query出现的次数,然后按照出现次数做快速/堆/归并排序虽可了。

   
方案3:与方案1类,但以召开完hash,分成基本上只文件后,可以交到多独文本来处理,采用分布式的架构来拍卖(比如MapReduce),最后再进行统一。

6、
给定a、b两单文本,各存放50亿只url,每个url各占64字节,内存限制是4G,让你摸出a、b文件共同之url?

   
可以估计每个文件安的深浅为5G×64=320G,远远胜出内存限制的4G。所以不容许以那个完全加载到外存中处理。考虑下分而治之的法门。

  1. 分而治之/hash映射:遍历文件a,对每个url求取图片 1,然后因所得到的值将url分别存储到1000独稍文件(记为图片 2)中。这样每个微文件之约为300M。遍历文件b,采取与a相同之方式以url分别存储到1000有些文件中(记为图片 3)。这样处理后,所有可能同样之url都在相应的粗文件(图片 4)中,不对应的略微文件未可能产生同之url。然后我们只是要求发生1000对准小文件被同样的url即可。
  2. hash统计:求诸对有些文件中一致之url时,可以管内部一个多少文件的url存储到hash_set中。然后遍历另一个微文件之每个url,看那是否在刚刚构建的hash_set中,如果是,那么就算是一起的url,存到文件里就是足以了。

    OK,此第一栽方式:分而治之/hash映射 + hash统计 +
堆/快速/归并排序,再看最终三道题,如下:

7、怎么当海量数据被搜索有重新次数最多的一个?

   
方案1:先做hash,然后求模映射为多少文件,求出每个微文件被又次数最多之一个,并记下重复次数。然后搜索有上一致步要出之多少中再度次数最多的一个就算是所求(具体参考前的修)。

8、上千万或上亿数据(有再),统计中出现次数最多之钱N个数据。

   
方案1:上千万或者上亿的多少,现在之机的内存应该力所能及存下。所以考虑使用hash_map/搜索二叉树/红黑树等来进行统计次数。然后便取出前N个冒出次数最多之数额了,可以用第2修提到的堆机制完成。

9、一个文书文件,大约产生一万行,每行一个歌词,要求统计有其中最为累出现的前方10独词,请于来思想,给出时复杂度分析。

   
 方案1:这题是考虑时间效率。用trie树统计每个词起的次数,时间复杂度是O(n*le)(le表示单词的平准长度)。然后是找来出现最为频繁的前10单词,可以据此堆来促成,前面的修中曾经提到了,时间复杂度是O(n*lg10)。所以究竟的辰复杂度,是O(n*le)与O(n*lg10)中较充分的哇一个。

 

    接下去,咱们来拘禁第二栽艺术,双层捅划分。

 

次、消息再次

地方在解决消息顺序问题常常,引入了一个新的问题,就是信再度。那么RocketMQ是怎样解决消息再次的题目呢?还是“恰好”不解决。

造成信息再次的根本原因是:网络不可达。只要经网交换数据,就无法避免这题目。所以解决此问题的办法就是是绕了是题材。那么问题便改为了:如果消费端收到两长条一样的音,应该怎么处理?

  1. 消费端处理消息之作业逻辑保持幂等性
  2. 保证各级条信息都生唯一编号都保险信息处理成和夺重表的日记同时起

第1长条很好理解,只要维持幂等性,不管来多少条还消息,最后处理的结果都如出一辙。第2修规律就是运用同摆放日志表来记录都处理成的消息的ID,如果新及之信息ID已经在日志表中,那么尽管不再处理及时长达信息。

第1条解决方案,很显眼应该以消费端实现,不属于信息网如实现的功用。第2长达好消息网贯彻,也得以业务端实现。正常状况下起还消息之概率其实挺有些,如果由于信息网来实现的话,肯定会针对信息网的吞吐量和大可用有震慑,所以最好好或者出于工作端好处理消息再次的题材,这为是RocketMQ不解决消息更的问题之缘由。

RocketMQ不保证信息不更,如果你的事情需要确保严格的莫重复消息,需要您自己于作业端去还。

密匙二、双层桶划分

 

双层桶划分—-其实本质上或分而治之的盘算,重在“分”的技巧上!
  适用范围:第k好,中位数,不另行或更的数字
  基本原理及中心:因为元素范围大可怜,不克用直接寻址表,所以经反复区划,逐步确定限制,然后最后在一个方可承受之界定外展开。可以经反复紧缩,双层只是一个例。
  扩展:
  问题实例:

     
  10、2.5亿个整数中检索有不又的整数的个数,内存空间不足以容纳这2.5亿只整数。
  有点像鸽巢原理,整数个数为2^32,也即是,我们好将马上2^32单数,划分为2^8单区域(比如用么文件表示一个区域),然后拿数据分离及不同之区域,然后不同之区域在利用bitmap就好直接解决了。也就是说要来足够的磁盘空间,就可以充分方便之解决。

       11、5亿单int找她的中位数。
  这个事例比上面很更明确。首先我们用int划分为2^16独区域,然后读取数据统计落至各级个区域里之一再的个数,之后我们根据统计结果就足以断定中位数落到特别区域,同时懂得此区域受到之第几非常屡屡刚好是中位数。然后第二破扫描我们特统计落于这个区域中之那些频繁就足以了。
  实际上,如果无是int是int64,我们得以经过3糟糕这样的剪切即可降低到得承受之档次。即好事先拿int64分成2^24独区域,然后确定区域之第几要命屡屡,在将该区域分为2^20单分支区域,然后确定是子区域之第几很屡屡,然后子区域里的反复之个数只发2^20,就可直接动用direct
addr table进行统计了。

 

其三、事务消息

RocketMQ除了支持普通消息,顺序消息,另外还支持工作消息。首先讨论一下哟是事情消息和支持工作消息之必要性。我们坐一个转帐的现象吧例来说明是问题:Bob向Smith转账100片。

于单机环境下,执行工作之状态,大概是底下这个样子:

单机环境下转账业务示意图

当用户增长及得程度,Bob和Smith的账户以及余额信息都不在同等台服务器上了,那么地方的流水线便改成了这般:

集群环境下转化业务示意图

此刻若会意识,同样是一个转会的政工,在集群环境下,耗时竟然成倍的加强,这肯定是匪能够接受之。那什么来逃避之题目?

大事务 = 小事务 + 异步

拿大事务拆分成多独小事务异步执行。这样基本上会用跨机事务的实践效率优化及和单机一致。转账的作业就得说变成如下两独小事务:

细节务+异步消息

贪图备受履行本地工作(Bob账户扣款)和发送异步消息应保证同时打响或又失败,也尽管是扣款成功了,发送信息一定要是打响,如果扣款失败了,就未克再次发送信息。那问题是:我们是先行扣款或者事先发送信息吧?

第一看下优先发送信息之动静,大致的示意图如下:

作业消息:先发送信息

是的题材是:如果消息发送成功,但是扣款失败,消费端就会花之音,进而向Smith账户加钱。

先发信息不行,那即便优先看款吧,大致的示意图如下:

事情消息-先扣款

存在的题材同方类似:如果扣款成功,发送信息失败,就见面起Bob扣钱了,但是Smith账户不加钱。

想必大家会出成千上万之办法来缓解此问题,比如:直接用发信息放到Bob扣款的事务中去,如果发送失败,抛来好,事务回滚。这样的处理方式也抱“恰好”不需缓解之极。

此处要证明一下:如果用Spring来治本事物的话,大可以拿发送信息之逻辑放到本地事物中失去,发送信息失败抛来好,Spring捕捉到好后便会见回滚此物,以之来确保本地事物和发送信息的原子性。

RocketMQ支持工作消息,下面来探视RocketMQ是怎么样来兑现之。

RocketMQ实现殡葬工作消息

RocketMQ第一阶段发送Prepared消息常,会将到消息的地方,第二级推行本地事物,第三号通过第一流将到的地址去顾消息,并修改信息之状态。

周密的公或又发现问题了,如果承认信息发送失败了怎么处置?RocketMQ会定期扫描消息集众多被的事物信息,如果发现了Prepared消息,它会朝着信息发送端(生产者)确认,Bob的钱到底是削弱了或者不曾减为?如果减了凡回滚还是延续发送确认信息也?RocketMQ会根据发送端设置的政策来决定是回滚还是累发送确认信息。这样便确保了音信发送和地面工作同时打响或以失败。

那么咱们来拘禁下RocketMQ源码,是哪些处理事务消息之。客户端发送业务消息的片段(完整代码请查看:rocketmq-example工下之com.alibaba.rocketmq.example.transaction.TransactionProducer):

// =============================发送事务消息的一系列准备工作========================================
// 未决事务,MQ服务器回查客户端
// 也就是上文所说的,当RocketMQ发现`Prepared消息`时,会根据这个Listener实现的策略来决断事务
TransactionCheckListener transactionCheckListener = new TransactionCheckListenerImpl();
// 构造事务消息的生产者
TransactionMQProducer producer = new TransactionMQProducer("groupName");
// 设置事务决断处理类
producer.setTransactionCheckListener(transactionCheckListener);
// 本地事务的处理逻辑,相当于示例中检查Bob账户并扣钱的逻辑
TransactionExecuterImpl tranExecuter = new TransactionExecuterImpl();
producer.start()
// 构造MSG,省略构造参数
Message msg = new Message(......);
// 发送消息
SendResult sendResult = producer.sendMessageInTransaction(msg, tranExecuter, null);
producer.shutdown();

接着查看sendMessageInTransaction措施的源码,总共分为3个等级:发送Prepared消息、执行本地工作、发送确认信息。

//  ================================事务消息的发送过程=============================================
public TransactionSendResult sendMessageInTransaction(.....)  {
    // 逻辑代码,非实际代码
    // 1.发送消息
    sendResult = this.send(msg);
    // sendResult.getSendStatus() == SEND_OK
    // 2.如果消息发送成功,处理与消息关联的本地事务单元
    LocalTransactionState localTransactionState = tranExecuter.executeLocalTransactionBranch(msg, arg);
    // 3.结束事务
    this.endTransaction(sendResult, localTransactionState, localException);
}

endTransaction方法会将请求发朝broker(mq server)夺创新工作消息的最后状态:

  1. 根据sendResult找到Prepared消息sendResult带有事务消息之ID
  2. 根据localTransaction更新信息的终极状态

如果endTransaction道执行破产,数据尚未发送到broker,导致工作消息之
状态更新失败,broker会晤时有发生回查线程定时(默认1分钟)扫描每个存储业务状态的报表文件,如果是曾经付出或者回滚的音信直接跳过,如果是prepared状态则会向Producer发起CheckTransaction请求,Producer会调用DefaultMQProducerImpl.checkTransactionState()方来拍卖broker的定时回调请求,而checkTransactionState见面调用我们的事体设置的断方法来控制是回滚事务还是继续执行,最后调用endTransactionOnewaybroker来更新信息之最终状态。

复回到转账的事例,如果Bob的账户的余额就压缩,且消息已发送成功,Smith端开始消费就漫漫信息,这个时就是见面产出消费失败和花过两个问题,解决过问题之思路就是是直接重试,直到消费端消费信息成功,整个过程遭到起或会见冒出信息再度的题材,按照前面的思绪解决即可。

花费事务消息

如此这般多可以化解消费端超时问题,但是一旦消费失败怎么收拾?阿里资给我们的解决方式是:人为解决。大家可以考虑一下,按照作业的流水线,因为某种原因Smith加款未果,那么要回滚整个流程。如果消息网一旦促成者回滚流程的话,系统复杂度将大大升级,且很易并发Bug,估计起Bug的几率会于花费失败的概率大群。这为是RocketMQ目前暂时没缓解此问题的由来,在规划实现信息网不时,我们要权衡是否值得花这样可怜的代价来化解这样一个油然而生概率非常小之题材,这吗是大家在化解疑难问题时得多多考虑的地方。

20160321补偿:在3.2.6本中易除工作消息的实现,所以这本不支持工作消息,具体情况请参考rocketmq的issues:
https://github.com/alibaba/RocketMQ/issues/65
https://github.com/alibaba/RocketMQ/issues/138
https://github.com/alibaba/RocketMQ/issues/156

密匙三:Bloom filter/Bitmap

季、Producer如何发送信息

Producer轮询某topic下的有班的方法来实现发送方的载荷均衡,如下图所示:

producer发送消息负载均衡

首先分析一下RocketMQ的客户端发送信息之源码:

// 构造Producer
DefaultMQProducer producer = new DefaultMQProducer("ProducerGroupName");
// 初始化Producer,整个应用生命周期内,只需要初始化1次
producer.start();
// 构造Message
Message msg = new Message("TopicTest1",// topic
                        "TagA",// tag:给消息打标签,用于区分一类消息,可为null
                        "OrderID188",// key:自定义Key,可以用于去重,可为null
                        ("Hello MetaQ").getBytes());// body:消息内容
// 发送消息并返回结果
SendResult sendResult = producer.send(msg);
// 清理资源,关闭网络连接,注销自己
producer.shutdown();

在整个应用生命周期内,生产者需要调用一破start方法来初始化,初始化主要得的任务来:

  1. 若没点名namesrv地点,将会晤活动寻址
  2. 起步定时任务:更新namesrv地址、从namsrv更新topic路由信息、清理已挂掉的broker、向装有broker发送心跳…
  3. 启航负载均衡的劳动

初始化完成后,开始发送信息,发送信息的最主要代码如下:

private SendResult sendDefaultImpl(Message msg,......) {
    // 检查Producer的状态是否是RUNNING
    this.makeSureStateOK();
    // 检查msg是否合法:是否为null、topic,body是否为空、body是否超长
    Validators.checkMessage(msg, this.defaultMQProducer);
    // 获取topic路由信息
    TopicPublishInfo topicPublishInfo = this.tryToFindTopicPublishInfo(msg.getTopic());
    // 从路由信息中选择一个消息队列
    MessageQueue mq = topicPublishInfo.selectOneMessageQueue(lastBrokerName);
    // 将消息发送到该队列上去
    sendResult = this.sendKernelImpl(msg, mq, communicationMode, sendCallback, timeout);
}

代码中得关怀之简单单主意tryToFindTopicPublishInfoselectOneMessageQueue。前面说过在producer初始化时,会启动定时任务得到路由于信息并更新到地面缓存,所以tryToFindTopicPublishInfo会面首先从缓存中获得topic路由信息,如果无获取到,则会友善失去namesrv得到路由于信息。selectOneMessageQueue道通过轮询的方法,返回一个阵,以高达负载均衡的目的。

倘Producer发送消息失败,会自动重试,重试的国策:

  1. 重试次数 < retryTimesWhenSendFailed(可安排)
  2. 究竟的耗时(包含重试n次的耗时) <
    sendMsgTimeout(发送信息不时传出的参数)
  3. 又满足上面两单原则后,Producer会选择另外一个队列发送信息

Bloom filter

至于什么是Bloom filter,请参考此文:海量数据处理的Bloom
Filter详解。
  适用范围:可以据此来实现数量字典,进行数量的判重,或者集合求交集
  基本原理及中心:
  对于原理来说十分简短,位数组+k个独立hash函数。将hash函数对应的值的位数组置1,查找时只要发现具有hash函数对应位都是1证明存在,很显著是历程并无包查找的结果是100%不易的。同时也未支持删除一个早已插入的重要字,因为该关键字对应之位会牵动到其它的主要字。所以一个简单易行的精益求精就是
counting Bloom filter,用一个counter数组代替位数组,就好支撑删除了。
  还有一个于主要之题材,如何根据输入元素个数n,确定位数组m的尺寸与hash函数只数。当hash函数个数k=(ln2)*(m/n)时错误率最小。在错误率不大于E的情形下,m至少要等于n*lg(1/E)才会代表任意n个因素的会师。但m还应该再充分把,因为还要保证bit数组里起码一半呢0,则m应该>=nlg(1/E)*lge
大概就是是nlg(1/E)1.44倍(lg代表因为2为的的对数)。
  举个例证我们借要错误率为0.01,则这m应大概是n的13加倍。这样k大概是8独。
  注意这里m与n的单位不同,m是bit为单位,而n则是盖素个数为单位(准确之就是不同因素的个数)。通常单个元素的长都是有很多bit的。所以使用bloom
filter内存上通常还是省去的。

  扩展:
  Bloom
filter将聚合中的因素映射到位数组中,用k(k为哈希函数个数)个映射位是否全1表示元素以匪以此集中。Counting
bloom
filter(CBF)将各类数组中的各级一样各扩展为一个counter,从而支持了元素的去除操作。Spectral
Bloom
Filter(SBF)将该同集合元素的出现次数关联。SBF采用counter中之顶小值来仿佛表示元素的产出频率。

     
  12、给你A,B两只公文,各存放50亿长条URL,每条URL占用64字节,内存限制是4G,让你寻找出A,B文件共同的URL。如果是三只甚至n个文件呢?

  根据是题目我们来计算下内存的占有,4G=2^32约是40亿*8大约是340亿,n=50亿,如果按出错率0.01毕竟需要的大致是650亿个bit。现在可用的凡340亿,相差并无多,这样或许会见使出错率上升些。另外假如这些urlip是逐一对应之,就可以变换成ip,则大大简单了。

   
同时,上文的第5修:给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让您追寻出a、b文件共同的url?如果允许发生必然之错误率,可以用Bloom
filter,4G内存大概可以代表340亿bit。将里面一个文本中之url使用Bloom
filter映射为就340亿bit,然后逐一读取另外一个文书之url,检查是否以及Bloom
filter,如果是,那么该url应该是齐之url(注意会生自然的错误率)。

五、消息存储

RocketMQ的信息存储是由consume queuecommit log配合到位的。

Bitmap

   
至于什么是Bitmap,请看此文:http://blog.csdn.net/v\_july\_v/article/details/6685962。下面关于Bitmap的利用,直接上题,如下第9、10志:

     
13、在2.5亿独整数中检索来未另行的整数,注,内存不足以包容这2.5亿只整数。

   
方案1:采用2-Bitmap(每个数分配2bit,00代表不设有,01意味着出现一样不良,10意味多次,11管意义)进行,共得外存2^32
* 2 bit=1
GB内存,还可承受。然后扫描这2.5亿个整数,查看Bitmap中相对应位,如果是00变01,01更换10,10维持无变换。所画完事后,查看bitmap,把针对应位是01底平头输出即可。
   
方案2:也不过下和第1书类似之不二法门,进行私分小文件的方式。然后以稍微文件中查找来非还的整数,并排序。然后再次展开联,注意去重复的因素。

      14、腾讯面试题:给40亿个不重复的unsigned
int的整数,没消除了序的,然后又为一个屡屡,如何迅速判断是累是否以那么40亿个数当中?

    方案1:frome
oo,用各图/Bitmap的方法,申请512M之内存,一个bit位代表一个unsigned
int值。读入40亿个数,设置相应的bit位,读入要询问的屡屡,查看相应bit位是否为1,为1意味是,为0表示未存在。

1、Consume Queue

consume queue凡信之逻辑队列,相当给字典的目录,用来指定消息于情理文件commit log达成的职位。

咱得以以安排中指定consumequeuecommitlog囤的目
每个topic生之每个queue犹有一个遥相呼应之consumequeue文件,比如:

${rocketmq.home}/store/consumequeue/${topicName}/${queueId}/${fileName}

Consume Queue文件组织,如图所示:

Consume Queue文件组织示意图

  1. 根据topicqueueId来组织文件,图中TopicA有有限个股列0,1,那么TopicA和QueueId=0组成一个ConsumeQueue,TopicA和QueueId=1组成另一个ConsumeQueue。
  2. 论消费端的GroupName来分组重试队列,如果消费端消费失败,消息将于发于重试队列中,比如图备受的%RETRY%ConsumerGroupA
  3. 随消费端的GroupName来分组死信队列,如果消费端消费失败,并重试指定次数后,仍然失败,则发朝死信队列,比如图备受之%DLQ%ConsumerGroupA

死信队列(Dead Letter
Queue)一般用来存放由于某种原因无法传递的音信,比如拍卖失败或者已经晚点的音讯。

Consume
Queue中存储单元是一个20许节定长之二进制数据,顺序写顺序读,如下图所示:

consumequeue文件存储单元格式

  1. CommitLog Offset是靠当时长达消息在Commit Log文件被的实际上偏移量
  2. Size存储着信息的轻重缓急
  3. Message Tag
    HashCode存储消息之Tag的哈希值:主要用来订阅时信息过滤(订阅时假如指定了Tag,会依据HashCode来很快搜索到订阅的信)

密匙四、Trie树/数据库/倒排索引

Trie树

  适用范围:数据量大,重复多,但是多少类小得放入内存
  基本原理及中心:实现方式,节点孩子的代表法
  扩展:压缩实现。

  问题实例:

  1. 发10独文件,每个文件1G,每个文件的各国一行都存放的凡用户的query,每个文件之query都或再度。要而以query的频度排序。
  2. 1000万配符串,其中微是一样的(重复),需要将更的浑去丢,保留没有再次的字符串。请问怎么统筹以及促成?
  3. 寻热门查询:查询串的重复度比较大,虽然总数是1千万,但如若除去重复后,不超过3百万独,每个不越255字节。
  4. 方的第8书写:一个文本文件,大约发生一万行,每行一个乐章,要求统计出中最为累出现的眼前10单词。其解决智是:用trie树统计每个词出现的次数,时间复杂度是O(n*le)(le表示单词的平准长度),然后是摸索有出现不过累之眼前10单词。

 

   
更多关于Trie树的牵线,请参见此文:从Trie树(字典树)谈到后缀树。

数据库索引
  适用范围:大数据量的增删改查
  基本原理及中心:利用多少的规划实现方式,对海量数据的增删改查进行处理。

   
关于数据库索引及其优化,更多而是参见此文:http://www.cnblogs.com/pkuoliver/archive/2011/08/17/mass-data-topic-7-index-and-optimize.html。同时,关于MySQL索引背后的数据结构及算法原理,这里还有一样篇大好之稿子:http://www.codinglabs.org/html/theory-of-mysql-index.html。

倒排索引(Inverted index)
  适用范围:搜索引擎,关键字查询
  基本原理及中心:为何让倒排索引?一栽索引方法,被用来囤于全文检索下某单词在一个文档或者千篇一律组文档中的囤积位置的照耀。
 以英文为条例,下面是只要受索引的公文:
    T0 = “it is what it is”
    T1 = “what is it”
    T2 = “it is a banana”
    我们即便能得到下面的反向文件目录:
   “a”:      {2}
    “banana”: {2}
    “is”:     {0, 1, 2}
   “it”:     {0, 1, 2}
   “what”:   {0, 1}
 检索的原则”what”,”is”和”it”将相应集合的搅和。

  正为索引开发出用来储存每个文档的一味词之列表。正朝着索引的查询往往满足每个文档有序频繁之全文查询以及每个单词在校验文档中的认证这样的询问。在正向索引中,文档占据了骨干的职务,每个文档指向了一个它们所含有的索引项的班。也就是说文档指向了它包含的那些单词,而反往索引则是不过词指为了蕴藏它的文档,很轻看是反向的干。
  扩展:
  问题实例:文档检索系统,查询那些文件包含了某单词,比如大规模的学术论文的最主要字搜索。

   
关于倒排索引的动,更多要参见:第二十三、四节:杨氏矩阵查找,倒排索引关键词Hash不重复编码实践,及第二十六章节:基于给定的文档生成倒排索引的编码和实践。

2、Commit Log

CommitLog:消息存放的物理文件,每令broker上的commitlog让本机所有的queue共享,不举行另外区别。
文件的默认位置如下,仍然可经部署文件修改:

${user.home} \store\${commitlog}\${fileName}

CommitLog的音信存储单元长度不固定,文件相继写,随机读。消息的存储结构如下表所示,按照号码挨个和编号对应的内容逐条存储。

Commit Log存储单元结构图

密匙五、外排序

  适用范围:大数额的排序,去还
  基本原理及中心:外排序的联结措施,置换选择败者树原理,最帅归并培育
  扩展:
  问题实例:
  1).有一个1G轻重缓急的一个文本,里面每一样实践是一个词,词的高低不超过16单字节,内存限制大小是1M。返回频数最高的100独词。
  这个数具有特别明朗的性状,词的深浅为16独字节,但是内存只出1M做hash明显不够,所以可以用来排序。内存可以当输入缓冲区使用。

   
关于多路归并算法和外排序的现实用场景,请参见此文:第十回、如何被10^7独数据量的磁盘文件排序。

3、消息存储实现

信息存储实现,比较复杂,也值得大家深切了解,后面会单独成和来分析(目前正在搜集素材),这小节只为代码说明一下切实的流程。

// Set the storage time
msg.setStoreTimestamp(System.currentTimeMillis());
// Set the message body BODY CRC (consider the most appropriate setting
msg.setBodyCRC(UtilAll.crc32(msg.getBody()));
StoreStatsService storeStatsService = this.defaultMessageStore.getStoreStatsService();
synchronized (this) {
    long beginLockTimestamp = this.defaultMessageStore.getSystemClock().now();
    // Here settings are stored timestamp, in order to ensure an orderly global
    msg.setStoreTimestamp(beginLockTimestamp);
    // MapedFile:操作物理文件在内存中的映射以及将内存数据持久化到物理文件中
    MapedFile mapedFile = this.mapedFileQueue.getLastMapedFile();
    // 将Message追加到文件commitlog
    result = mapedFile.appendMessage(msg, this.appendMessageCallback);
    switch (result.getStatus()) {
    case PUT_OK:break;
    case END_OF_FILE:
         // Create a new file, re-write the message
         mapedFile = this.mapedFileQueue.getLastMapedFile();
         result = mapedFile.appendMessage(msg, this.appendMessageCallback);
     break;
     DispatchRequest dispatchRequest = new DispatchRequest(
                topic,// 1
                queueId,// 2
                result.getWroteOffset(),// 3
                result.getWroteBytes(),// 4
                tagsCode,// 5
                msg.getStoreTimestamp(),// 6
                result.getLogicsOffset(),// 7
                msg.getKeys(),// 8
                /**
                 * Transaction
                 */
                msg.getSysFlag(),// 9
                msg.getPreparedTransactionOffset());// 10
    // 1.分发消息位置到ConsumeQueue
    // 2.分发到IndexService建立索引
    this.defaultMessageStore.putDispatchRequest(dispatchRequest);
}

密匙六、分布式处理的Mapreduce

      适用范围:数据量大,但是多少列小得放入内存
  基本原理及中心:将数据交由不同的机械去处理,数据划分,结果归约。
  扩展:
  问题实例:

  1. The canonical example application of MapReduce is a process to count
    the appearances of each different word in a set of documents:
  2. 海量数据分布在100台计算机受到,想个办法高效统计出这批数量的TOP10。
  3. 总计发生N个机器,每个机器上发N个数。每个机器太多存O(N)个数并对其操作。如何找到N^2个数之中数(median)?

 

   
更多具体阐释请参见:起Hadhoop框架和MapReduce模式中谈海量数据处理,及MapReduce技术之发端询问和学习。

4、消息之目文件

如果一个信包含key值的说话,会动用IndexFile存储消息索引,文件的内容结构使图:

信索引

目录文件要用来因key来询问信息之,流程主要是:

  1. 冲查询的 key 的 hashcode%slotNum 得到具体的槽的职(slotNum
    是一个目录文件里含的太充分槽的多寡,例如图备受所示 slotNum=5000000)
  2. 冲 slotValue(slot
    位置对应之值)查找到索引项列表的结尾一件(倒序排列,slotValue
    总是指于行的一个索引项)
  3. 所有历索引项列表返回查询时限定外的结果集(默认一坏最好老返回的 32
    修记下)

参考文献

  1. 十道海量数据处理面试题和十独措施好总结;
  2. 海量数据处理面试题集锦与Bit-map详解;
  3. 十一、从头到尾彻底解析Hash表算法;
  4. 海量数据处理的Bloom
    Filter详解;
  5. 自Trie树(字典树)谈到后缀树;
  6. 其三章续、Top
    K算法问题之兑现;
  7. 第十章节、如何被10^7个数据量的磁盘文件排序;
  8. 第二十三、四节:杨氏矩阵查找,倒排索引关键词Hash不重复编码实践;
  9. 第二十六章节:基于给定的文档生成倒排索引的编码和执行;
  10. 由Hadhoop框架和MapReduce模式中谈海量数据处理;
  11. 第十六~第二十章:全排,跳台阶,奇偶排序,第一只只现出同等软顶题材;
  12. http://blog.csdn.net/v\_JULY\_v/article/category/774945;
  13. STL源码剖析第五节,侯捷著。
六、消息订阅

RocketMQ信订阅有少数种植模式,一种植是Push模式,即MQServer主动为消费端推送;另外一栽是Pull模式,即消费端在急需经常,主动至MQServer拉取。但在现实贯彻时,Push和Pull模式还是采用消费端主动拉取的艺术。

第一看下消费端的载重均衡:

消费端负载均衡

花端会通过RebalanceService线程,10秒钟做同样差因topic下之持有班负载:

  1. 遍历Consumer下的有所topic,然后因topic订阅所有的音
  2. 得同一topic和Consumer Group下的兼具Consumer
  3. 然后根据具体的分配政策来分配消费队列,分配的国策包含:平均分配、消费端配置等

犹如上图所示:如果起 5 个班,2 个 consumer,那么首先单 Consumer 消费 3
单序列,第二 consumer 消费 2
只班。这里运用的便是平均分配策略,它相仿于分页的长河,TOPIC下面的装有queue就是记录,Consumer的个数就一定给总的页数,那么每页有稍许条记下,就象是于有Consumer会消费如何队列。

经过这样的国策来上约上之平均消费,这样的计划性也堪好方面的品位扩展Consumer来提高消费能力。

消费端的Push模式是经丰富轮询的模式来落实之,就像下图:

Push模式示意图

Consumer端每隔一段时间主动为broker发送拉音请求,broker在接到Pull请求后,如果起消息就是及时返回数据,Consumer端收到返回的音后,再回调消费者设置的Listener方法。如果broker在收受Pull请求时,消息队列里从未数,broker端会阻塞请求直到有多少传递或超时才回去。

理所当然,Consumer端是由此一个线程将封堵队列LinkedBlockingQueue<PullRequest>中的PullRequest出殡至broker拉取消息,以戒Consumer一致被卡住。而Broker端,在接至Consumer的PullRequest时不时,如果发现无消息,就会拿PullRequest摈弃到ConcurrentHashMap中缓存起来。broker于起步时,会启动一个线程不歇的打ConcurrentHashMap取出PullRequest检查,直到有多少返回。

后记

   
经过地方这么多海量数据处理给试题的轰炸,我们依然得以看这仿佛题目是产生早晚之缓解方案/模式之,所以,不必将那个神化。当然,这类面试题所蕴涵的题目要么比较简单的,若你当及时上头来重新多实践经验,欢迎随时来信及自己弗吝分享:zhoulei0907@yahoo.cn。当然,自会注明分享者及自。

   
不过,相信您呢早已发现及,若单纯论海量数据处理给试题,本blog内之有关海量数据处理对试题的篇章都盈盈了公可知以网上所找到的70~80%。但多少,必须依总责的敬告大家:无论是这些海量数据处理对试题可以,还是算法也好,70~80%之总人口未是倒以即时有限方面,而是倒在基础之上,所以,无论任何时候,基础极重点,没了根基,便什么都未是。最后,推荐国外相同对试题网站:http://www.careercup.com/,以及个体正在读的Redis/MongoDB绝佳站点:http://blog.nosqlfan.com/。

    OK,本文若发生另问题,欢迎随时不吝留言,评论,赐教,谢谢。完。

 

 
  PS:csdn最近开评选10百般博客专栏,投票地址为:http://event.blog.csdn.net/topcolumn/topcolumn.aspx。我之3只专辑是编程语言栏目中之第1个:经典算法研究http://blog.csdn.net/column/details/Dijkstra.html;第6单:微软面试100书系列http://blog.csdn.net/column/details/ms100.html;第10只:程序员编程艺术http://blog.csdn.net/column/details/taopp.html。 如果你看自己形容的尚实施,欢迎选我。现在去投票,有空子以到一半年VIP卡,从而免积分产充斥任何资源。本月底2012.03.30截至。感谢。

七、RocketMQ的另特色

面前的6单特征还是多还是点至竣工,想要深切摸底,还索要大家多查看源码,多多在实质上中采用。当然除了已经提到的风味外,RocketMQ还支持:

  1. 定时信息
  2. 消息的刷盘策略
  3. 当仁不让同步策略:同步双写、异步复制
  4. 海量信息堆积能力
  5. 很快通信
  6. …….

其中涉嫌到之诸多规划思路以及缓解办法还值得我们深刻钻研:

  1. 信的积存设计:既使满足海量信息之积聚能力,又比方满足无限快的询问效率,还要管写副的频率。
  2. 高速之通信组件设计:高吞吐量,毫秒级的消息投递能力且离不起来飞之通信。
  3. …….

RocketMQ最佳实践

一律、Producer最佳实践

1、一个使尽可能用一个 Topic,消息子类型用 tags 来标识,tags
可以由用自由设置。只有发送信息设置了tags,消费方在订阅消息时,才得以行使
tags 在 broker 做信息过滤。
2、每个消息在作业规模的绝无仅有标识码,要安装到 keys
字段,方便将来稳住信息丢失问题。由于是哈希索引,请务必保管 key
尽可能唯一,这样可以避免地下的哈希冲突。
3、消息发送成功还是失败,要打印消息日志,务必要打印 sendresult 和 key
字段。
4、对于信息不可丢应用,务必要起信息重发机制。例如:消息发送失败,存储到数据库,能出定时程序尝试重发或者人工触发重发。
5、某些应用如果未体贴消息是否发送成功,请直接使用sendOneWay主意发送信息。

次、Consumer最佳实践

1、消费过程要就幂等(即花费端去再)
2、尽量以批量术消费方式,可以老酷程度上加强消费吞吐量。
3、优化每条消息消费过程

其三、其他安排

丝上理应关闭autoCreateTopicEnable,即以安排文件中拿该安为false

RocketMQ于殡葬信息不时,会首先获得路由于信息。如果是初的信,由于MQServer上面还不曾开创对应之Topic,这个时候,如果地方的配备打开的话,会回去默认TOPIC的(RocketMQ会在列台broker点创建名也TBW102的TOPIC)路由于信息,然后Producer见面择一样玉Broker出殡信息,选中的broker以存储信息时,发现消息的topic尚从未创造,就见面自动创建topic。后果便是:以后所有拖欠TOPIC的音信,都拿发送到及时大broker及,达不交负载均衡的目的。

因而冲目前RocketMQ的计划,建议关闭自动创建TOPIC的效用,然后因消息量的尺寸,手动创建TOPIC。

RocketMQ设计息息相关

RocketMQ的统筹而:

每台PC机器都或宕机不可服务
擅自集群都来或处理能力不足
不过特别之景必会发出
内网环境要低顺延来提供最佳用户体验

RocketMQ的第一设计:

分布式集群化
强数据安全
海量数据堆积
毫秒级投递延迟(推拉模式)

立刻是RocketMQ在规划时之若前提与要到的作用。我眷恋这些使适用于拥有的系规划。随着我们系的服务的多,每位开发者都使顾自己之顺序是否是单点故障,如果挂了应当怎么过来、能无克怪好的水平扩展、对外的接口是否足够高效、自己管理的数额是否足够安全……
多多规范自己之筹划,才能够出有快速健壮的顺序。

参考资料
  1. RocketMQ用户指南
  2. RocketMQ原理简介
  3. RocketMQ最佳实践
  4. 阿里分布式开放消息服务(ONS)原理与实施2
  5. 阿里分布式开放消息服务(ONS)原理和执行3
  6. RocketMQ原理分析

备考:水平有限,难免疏漏,如果问题要留言
本文就联手创新至微信公众号:轻描淡写CODE
»
分布式开放消息网(RocketMQ)的法则及履行

发表评论

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