事件流如何提高应用程序的扩展性、可靠性和可维护性

标签: 事件 应用程序 扩展 | 发表时间:2015-03-31 18:39 | 作者:
出处:http://kb.cnblogs.com/

  关于事件流处理,在不同的场景中有不同的概念。有人称之为流处理,有人称之为事件溯源或CQRS,还有人称之为“复杂事件处理(Complex Event Processing)”。不管名称是什么,它们的基本原则都是一样的。Martin Kleppmann是 Apache Samza的贡献者。在本文中,我们将跟随 他的思路深入理解这些概念,以便帮助我们设计更好的系统。

  “流处理(stream processing)”源于LinkedIn构建大规模数据系统的经验,并在开源项目 Apache Kafka和Apache Samza中实现。Martin以Google Analytics为例具体介绍了这一概念。Google Analytics是一小段JavaScript代码,可以追踪哪个访问者访问了哪个网页。然后,系统管理员可以研究这些数据,并按照时间段、URL等划分这些数据。为了实现这个目的,每次用户访问一个页面时,就需要记录一个事件来反映这个事实。页面访问事件可能是(图1)这样的结构:

  每个事件都是包含上述信息的一个简单不变的事实。它只简单地记录已发生的事情。然后,我们就可以从这些页面访问事件中生成图形仪表板。通常来说,这些事件可以使用(图2)所示的其中一种方式存储:

   选项(a):在每个事件进来的时候将其存储,并把它们全部转存到一个大型的数据库、数据仓库或Hadoop集群中。在需要时,就可以在数据集上执行查询。这个过程会扫描所有事件,或者至少是某个大型的数据子集,并动态地完成聚合。

  选项(b):如果每个事件都存储数据量太大的话,可以选择存储事件的聚合结果。比如,如果要记录某个事件的发生次数,那么就可以在这个事件进来时将计数器加1。我们还可以将多个计数器保存在 OLAP立方中。有了OLAP立方,当需要查找一个URL在某一天的访问量时,直接读取相应URL和日期组合的计数器就可以了。这样就只需要读取一个值,而不需要扫描一个很长的事件列表。

  选项(a)的好处是,存储原始事件数据可以最大化分析的灵活性。比如,可以跟踪某个人以什么顺序访问了哪些页面,采用选项(b)就无法实现。这种分析对于一些离线处理任务非常重要,比如训练一个推荐系统。在这种应用场景下,最好是保存原始事件。

  不过,选项(b)也有它的用途,尤其是需要实时决策或响应的时候。比如,为了防止别人破坏网站,可能需要引入一个访问频率限制,在一个小时内一个特定的IP只允许请求100次;如果客户端超出这个限制,就阻塞它。这时,通过原始数据存储实现效率将非常低下,因为系统需要不断地重新扫描事件历史才能确定某个人是否超出了限制。而针对每个IP每个时间窗口维护一个计数器将会更高效。总之,存储原始事件和存储聚合结果都是有用的,只不过应用场景不同。

  对于选项(b),在最简单的情况下,可以让Web服务器直接更新聚合结果。这时,可以将计数器保存在像memcached或Redis这样具有原子增量操作的缓存中。每次Web服务器处理一个请求,就直接向缓存发送一条增量命令。更复杂一点,可以引入事件流(如图3),或者消息队列,或者事件日志。流上的事件与(图1)中PageViewEvent记录相同。

  这种架构的好处是,同样的事件数据可以供多个消费者使用,不同的消费者完成不同的任务,非常灵活和易于扩展。

  “事件溯源(Event sourcing)”是一个同流处理类似的概念,只不过它出自领域驱动设计社区。它关注数据在数据库中的存储结构。这里将以电商网站的购物车为例:

  如果用户123将产品999的数量改成了3,那么系统将通过UPDATE操作实现数据修改:

  不过,按照事件溯源的思想,这不是一个好的数据库设计方式,因为它没有记录购物车每次变化的信息,即丢失了历史操作信息。因此,在用户123初次添加产品999的时候,系统应该记录AddToCart事件;当用户改变主意想买3个999时,系统接着记录UpdateCartQuantity事件。总之,用户对购物车的每次操作都记为一个单独的事件。这就是事件溯源的本质:将每次写操作记为一个不可变事件,而不是对数据库执行破坏性写入。

  可以发现,它同流处理的例子(关于Google Analytics)一样:(a)存储原始事件;(b)存储聚合结果。

  通过进一步思考可以观察到,(a)是理想的数据写入形式,只需要将事件追加到日志尾部,而不需要更新多个不同的表。这对数据库而言是一种最简单、最快速的写入方式。另一方面,(b)是理想的数据读取形式。比如,在用户想知道购物车中有什么的时候,他并不会关心购物车中产品的变化历史,所以直接读取聚合结果会获得最好的性能。

  为了帮助我们更深入的理解上述概念,Martin又分别举了Twitter、Facebook和Wikipedia的例子。本文就不一一赘述了,感兴趣的读者可以查看 原文

  现在,让我们回到有关事件流的讨论。不管是流处理,还是事件溯源,只要有了事件流,就可以完成以下工作:

  • 获取所有的原始事件(也许还要做一点转换),然后将它们加载到一个大型的数据仓库中供分析人员使用;
  • 更新全文搜索索引,使用户可以搜索最新数据;
  • 更新缓存,使系统可以从快速缓存中读取数据,并保证缓存中的数据是最新的;
  • 通过对事件流进行处理创建一个新的事件流,然后将后者作为另一个系统的输入。

  与传统的数据库使用方法相比,采用类似事件溯源的方法是一个重大的变革。这项变革带来了如下好处:

  • 松耦合——数据读写使用不同的数据库模式,读取的数据经由写入的数据转换而来,应用程序不同部分之间的耦合度降低了;
  • 读写性能——规范化(写入快)和非规范化(读取快)的争论源于数据读写使用同一模式的假设,如果数据读写使用不同的数据库模式,读写速度都会得到提升;
  • 扩展性——因为事件流是一种简单的抽象,而且允许开发人员将应用程序分解成流的生产者和消费者,所以很容易跨机器并行和扩展;
  • 灵活性——原始事件简单、明确,“模式迁移”不会造成多大影响;而向用户展示数据要复杂得多,但如果有一个转换过程可以实现从原始事件到缓存内容的转换,那么当需要新的用户界面时,只需要使用新的逻辑构建新的缓存;
  • 错误场景——原始事件是不变的事实,如果系统出现问题,那么开发人员总是可以用相同的顺序将事件重放。

  这里需要注意,实际上,数据库写操作通常都有一个类似事件的 不变性,大部分数据库都有的“写前日志(write-ahead log)”本质上就是一个写操作的事件流,虽然在不同的数据库中实现形式可能不同,如PostgreSQL、InnoDB和Oracle中的MVCC机制,CouchDB、Datomic和LMDB中的追加式B树。

  接下来,Martin介绍了如何在应用程序层面上使用事件流。

  他用的比较多的是Apache Kafka和Apache Samza。前者是一个消息代理,就像一个发布-订阅消息队列,一秒钟可以处理包含数百万条消息的事件流,并将它们永久存储到磁盘上及跨机器复制。后者是与Kafka搭配使用的处理过程,开发人员可以用它编写代码,消费输入流,生产输出流。

  除了Samza之外,开发人员还可以选择 StormSpark Streaming这两种最流行的流处理框架。关于它们之间的区别,感兴趣的读者可以查看 Samza文档。这些分布式流处理框架均源于互联网公司。它们都关注底层的一些事情:如何将流处理扩展到多台机器;如何将Job部署到集群;如何处理故障;如何在多租户环境下实现可靠的性能。它们像MapReduce更多一些,而像数据库更少一些。

  相比之下,还有一些面向流处理的高级语言,如复杂事件处理(CEP)。使用CEP,可以编写查询或规则来匹配满足特定模式的事件。这些查询或规则与SQL查询类似,只不过CEP引擎会不断的查找事件流来匹配查询,并在匹配成功时发送通知。这对于欺诈检测或业务流程监控非常有用。

  还有一个相关概念是在流上进行全文搜索。它是说,在流上事先注册一个查询,当有事件匹配查询时发送通知。这里有一些与此相关的 试验性工作。以下是其它一些与流处理相关的概念:

  • Actor框架——像Akka、Orleans和Erlang OTP等框架也是基于不可变事件的流。不过,它们更多的是一种并发机制,而不是数据管理机制;
  • “响应式(Reactive)”——它似乎是一个定义松散的 概念集合,像函数响应式编程,主要是将事件流提供给用户界面使用;
  • 变更数据捕获(CDC)——按照我们熟悉的方式使用数据库,但要将任何插入、更新和删除操作抽取到一个数据变更事件流中。

相关 [事件 应用程序 扩展] 推荐:

事件流如何提高应用程序的扩展性、可靠性和可维护性

- - 博客园_知识库
  关于事件流处理,在不同的场景中有不同的概念. 有人称之为流处理,有人称之为事件溯源或CQRS,还有人称之为“复杂事件处理(Complex Event Processing)”. 不管名称是什么,它们的基本原则都是一样的. Martin Kleppmann是 Apache Samza的贡献者. 在本文中,我们将跟随 他的思路深入理解这些概念,以便帮助我们设计更好的系统.

应用程序扩展性实现的十宗罪

- - ITeye资讯频道
可扩展性方面专家Sean Hull曾发表文章指出实现 可扩展性的五大毒药,最近他又指出了实现 可扩展性的五大致命错误. 一、缓慢的磁盘I/O - RAID 5 -多用户的EBS. RAID 10可以提供良好的数据保护,同时具备良好 的读写性能. RAID 5设计意味着性能差,失败后修复时间长. 在AWS上考虑使用预设的IOPS解决IO瓶颈问题.

我使用的几个好用的Chrome应用程序和扩展

- - 博客园_首页
(刚才图片挂了,现在好了,不好意思)谷歌Chrome自推出以来已经从一个简单的浏览器演变成一个复杂的浏览器,这得益于根据浏览器写出的非常有用和强大的扩展. 作为一名开发人员,我们关注的是网页设计和开发部分的那些插件对我们有帮助,几个比较熟悉的插件像Firebug Lite和Web Developer大家都知道,我就不扯了,今天扯一下那些你可能不知道的对于开发非常有帮助的插件,在此做个总结,看看你用过几个,我敢肯定你会发现它们非常有用.

Android 应用程序

- - CSDN博客推荐文章
Android 应用程序由四个模块构造而成:Activity、Intent 、Content Provider 、Service. 下面简单介绍一下如下模块的含义:. 1、Activity  "活动". 一个Activity就是单独的屏幕,每一个活动都被实现为一个独立的类,并且从活动基类中继承而来,活动类将会显示由视图控件组成的用户接口并对事件作出响应.

iPhone应用程序推荐

- sylvia - 月光博客
  本文将为大家推荐一些笔者非常喜欢的iPhone应用程序. 注意,并不怎么包括游戏,因为笔者不太喜欢玩游戏,要玩也只玩小游戏. 这也有些遗憾,毕竟iPhone最大的卖点就是丰富的游戏了. 本文主要是推荐实用的软件和系统工具. 对新手应该帮助比较大,老鸟们也可以参考一下. 而且本文也不提供下载链接与安装方法.

Android 一个应用程序调用另一个应用程序

- - CSDN博客推荐文章
实现行业应用调用我们可以Get到哪些技能. * Activity的singleTask的启动模式 * 界面跳转的基本实现 * 前台Service的基本介绍和实现 * SharedPreference的简单用法. 在XHL应用程序中去调用MPos应用程序,借助MPos的一些界面完成特殊的功能. (1)创建名为XHL的应用程序.

优秀的WEB应用程序

- DayuLu - 互联网的那点事
今天我们将分享给大家一批优秀的WEB应用程序. 比如,大家可能用过在线的调色工具,Adobe也推出过在线的Photoshop软件. 这些程序或许就是未来软件程序的基础. 随着云处理和网络速度的飞速发展,这将是个好的趋势. 人们只需要一台在线的电脑就可以找到需要的应用程序,而不需要在自己电脑上安装复杂的文件.

Eclipse开发Android应用程序入门

- Bingnan - 酷壳 - CoolShell.cn
原文出处:http://www.smashingmagazine.com/2010/10/25/get-started-developing-for-android-with-eclipse/. 如今的移动设备应用程序开发充满着让人振奋的东西. 功能强大的硬件支持,平板电脑,多样的软件平台(塞班 OS,iOS,WebOS,Windows Phone 7…),移动设备开发者前景充满了机会和挑战.

开源应用程序架构

- WCM - LinuxTOY
建筑师会在训练过程中学习并了解上千年来由不同大师所设计的建筑,而软件工程师却鲜有这样的机会去了解现实中的软件架构是什么样子. 该书列举了以下开源软件架构设计:. 该书依照 Creative Commons Attribution 3.0 Unported 发布,既可以在线阅读,也可以在 Lulu 上购买纸质印刷版本和 PDF 电子书版本(其他格式的电子书版本正在制作中).

Web应用程序的开发步骤

- xxg - 月光博客
  如今已进入了web2.0高速发展的互联网时代,各种互联网的Web应用程序如雨后春笋般出现. 那么作为一名Web开发人员,怎样去开发一款优秀的Web应用程序呢. 这个问题没有一个简单的答案,甚至那些教育机构都未必能清楚的知道. 所以,像大多数在这个领域里的web开发人员一样,我们只是通过去做,去实验才学会了这些.