DelayedOperationPurgatory之DelayedOperation pool
purgatory就是炼狱的意思。
当一个DelayedOperation需要被delay时,它就被放到DelayedOperationPurgatory,相当于进行一个等待池。上一篇blog提到过,DelayedOperation想要摆脱delay状态,需要由事件来触发对它状态的检查,或者是超时时间到了。
这个逻辑看起来挺简单,但高效实现却挺复杂。0.9.0版本的Kafka重新设计了这个purgatory(相比0.8版本),设计思路在Kafka的这篇文档Purgatory Redesign Proposa。我翻译并注释了一下,放在Kafka之Purgatory Redesign Proposal (翻译)
purgatory的实现使用了两个缓存,这里先讲第一个。
直观的,我们需要一个key绑定到DelayedOperation上,来说明这个DelayedOperation会由哪些事件触发,而且一个DelayedOperation可以绑定到多个key, 一个key也可能跟多个DelayedOperation有关。所以这是一个多对多的映射,一边是事件,一边是DelayedOperation。
DelayedOperation pool
DelayedOperationPurgatory就提供了这种功能。它把这种映射保存到一个Pool里。这个Pool实际上是对一个ConcurrentHashMap的封装.
private val watchersForKey = new Pool[Any, Watchers](Some((key: Any) => new Watchers(key)))
Pool构造器的参数是一个value factory,即当这个pool里一个key没有value时,就用这个函数生成一个value。所以,对于value为空的key,这个pool就会构造一个watch这个key的Watchers.
Watchers
这个Pool的key是Any类型,也就是Scala里所有对象的基类,value是Watchers。注释里这么描述Watchers的
A linked list of watched delayed operations based on some key
Watchers把这些DelayedOperation保存在自己的一个instance field里
private[this] val operations = new LinkedList[T]()
由于Watchers是DelayedOperationPurgatory的内部类,T就源于DelayedOperationPurgatory的签名
class DelayedOperationPurgatory[T <: DelayedOperation](purgatoryName: String, brokerId: Int = 0, purgeInterval: Int = 1000)
extends Logging with KafkaMetricsGroup
所以operations这个域里保存的就是一个DelayedOperation的列表。
所以,DelayedOperationPurgatory用来保存DelayedOperation的数据结构是一个Map[Any, List[DelayedOpertion]]的结构。
对于Watchers来说,有两件事要做
- 当它关注的key有事件发生时,需要调用它的方法来遍历operations,找出其中可以被complete(即不再被delay)的operation。这个方法就是tryCompleteWatched
- 由于一个DelayedOperation可以对应多个key,所以当这个Watchers对应的key没有被触发,它保存的operations里的元素仍然可能由于其它的key触发而而被complete。所以外界需要能主动地检测这个Watchers里的哪些operation已经被complete了,并且移除这些元素。这个方法就是purgeCompleted。
做这两件事情的实机很重要,下面来分析一下
- 第一件事,在产生事件的地方进行检测就好。比如fetch线程处理fetch请求的过程,以及produce request的处理过程中,可以调用tryCompleteWatched。
- 第二件事的处理实机比较不好确定。因为当把一个request从某个key的watchers中移除以后,它可能还在另一个key的watchers里。而每次移除一个request,都要调用purgeCompleted显然不现实。但是0.9.0的实现中引用了新的数据结构来对request的超时进行检测,通过它可以准确获得某个时刻在purgatory中的请求数量(但并不是server中的DelayedOperation的数量,因为超时的DelayedOperation会被放入一个线程池执行它的回调,所以总的数量还需要加上线程池中的Operation数量, 而且这个线程池是一个FixedThreadPool,它使用一个无界的queue)。具体的作法请参照Kafka之Purgatory Redesign Proposal (翻译)
DelayedOperationPurgatory之DelayedOperation pool的更多相关文章
- DelayedOperationPurgatory之purgatory的实现
purgatory的超时检测 当一个DelayedOpeartion超时(timeout)时,它需要被检测出来,然后调用它的回调方法.这个事情看起来很简单,但做好也并不容易. 0.8.x的Kafka的 ...
- 添加 Pool Member - 每天5分钟玩转 OpenStack(123)
我们已经有了 Load Balance Pool "web servers"和 VIP,接下来需要往 Pool 里添加 member 并学习如何使用 cloud image. 先准 ...
- 创建 Pool & VIP - 每天5分钟玩转 OpenStack(122)
上节完成了 LBaaS 配置,今天我们开始实现如下 LBaaS 环境. 环境描述如下: 1. 创建一个 Pool “web servers”. 2. 两个 pool member “WEB1” 和 “ ...
- [转载】——故障排除:Shared Pool优化和Library Cache Latch冲突优化 (文档 ID 1523934.1)
原文链接:https://support.oracle.com/epmos/faces/DocumentDisplay?_adf.ctrlstate=23w4l35u5_4&id=152393 ...
- Ceph RGW 创建默认的pool
使用Ceph-deploy完成RGW服务部署后(最好是在部署RGW服务前建立如下这些pool),使用sudo ceph osd lspools 命令,会发现RGW自动以默认参数创建了N个rgw相关的p ...
- golang 裸写一个pool池控制协程的大小
这几天深入的研究了一下golang 的协程,读了一个好文 http://mp.weixin.qq.com/s?__biz=MjM5OTcxMzE0MQ==&mid=2653369770& ...
- 如何在Windows 2003+IIS6的环境下找回应用程序池(application pool)中的服务账号密码
上一篇文章说了说如何在Win2008+iis7中取出SharePoint管理账号密码的方法. 整个过程简单的讲,就是通过使用要找回密码的账号用来在SharePoint中创建一个临时的Web Appli ...
- 备忘-Sql server Timeout expired 超时时间已到. 达到了最大池大小 错误及Max Pool Size设置
select * from sysprocesses where dbid= db_id('数据库名') 通过此语句可查看目前所有的连接进程 不够了就必须设置Max Pool Size,理论最大值为3 ...
- SQL Server 2014新特性探秘(2)-SSD Buffer Pool Extension
简介 SQL Server 2014中另一个非常好的功能是,可以将SSD虚拟成内存的一部分,来供SQL Server数据页缓冲区使用.通过使用SSD来扩展Buffer-Pool,可以使得大量随 ...
随机推荐
- MATLAB 生成 COM 步骤
环境: 操作系统:windows xp sp3 MATLAB:Version 7.1.0.246(R14) Service Pack 3 第一步:安装编译器(如果已经安装则可跳过此步) 在MATLAB ...
- 原生js实现addClass,removeClass,hasClass方法
function hasClass(elem, cls) { cls = cls || ''; if (cls.replace(/\s/g, '').length == 0) return false ...
- JavaScript 弹窗
JavaScript 弹窗 可以在 JavaScript 中创建三种消息框:警告框.确认框.提示框. 警告框 警告框经常用于确保用户可以得到某些信息. 当警告框出现后,用户需要点击确定按钮才能继续进行 ...
- uml的关联多重度
UML中关联的多重度是指一个类的实例能够与另一个类的多少个实例相关联,这个“多少”被称为关联角色的多重度指定关联一端的多重度.也可以这样理解:在关联另一端的类的每个对象要求在本端的类必须有多 少个对象 ...
- Linux实现的IEEE 802.q VLAN
本文转载自: http://blog.chinaunix.net/uid-20786208-id-4291059.html Technorati 标签: Linux VLAN ---------- ...
- USB时钟为什么是48MHz
在学习2440的USB配置时钟中,发现它的时钟需要设置成48MHz固定的,这个我就来兴趣了,为什么这里面USB的时钟一定要是48M呢?在网上找了众多文章,都是讲解如何配置2440的MPLL和U ...
- Spark RDD整理
参考资料: Spark和RDD模型研究:http://itindex.net/detail/51871-spark-rdd-模型 理解Spark的核心RDD:http://www.infoq.com/ ...
- js设计模式(7)---装饰者模式
0.前言 下午做事效率很低,无精打采的,整个脑子就跟浆糊一样,看看时间一点点流去,心中只能无可奈何,哎,码农的激情难道就这么容易熄灭吗? 1.该模式的使用情况 假如我们想给对象增加功能,但是又不想修改 ...
- php中如何防止表单的重复提交
在php中如何防止表单的重复提交?其实也有几种解决方法. 下面小编就为大家介绍一下吧.需要的朋友可以过来参考下 代码: <?php /* * php中如何防止表单的重复提交 * by www.j ...
- 重拾C,一天一点点_2
类型转换一般来说,如果二元运算符的两个操作数具有不同的类型,较低的类型提升为较高类型,结果为较高类型.表达式由float类型的操作数不会自动转换为double类型.使用float类型主要是为了在使用较 ...