🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# BigData 使用 Erlang,C 和 Lisp 对抗移动数据海啸 > 原文: [http://highscalability.com/blog/2012/11/26/bigdata-using-erlang-c-and-lisp-to-fight-the-tsunami-of-mobi.html](http://highscalability.com/blog/2012/11/26/bigdata-using-erlang-c-and-lisp-to-fight-the-tsunami-of-mobi.html) ![](https://img.kancloud.cn/49/9a/499ace65d7ec6fab129cb2bba9b8866f_195x125.png) *这是 [Jon Vlachogiannis](http://www.linkedin.com/in/johnvlachoyiannis) 的来宾帖子。 Jon 是 [BugSense](http://www.bugsense.com/) 的创始人和首席技术官。* BugSense,是一个错误报告和质量指标服务,每天跟踪数千个应用程序。 当移动应用崩溃时,BugSense 可帮助开发人员查明并解决问题。 该初创公司向其客户提供一流的服务,其中包括 VMWare,三星,Skype 和数以千计的独立应用程序开发人员。 跟踪超过 200M 的设备需要快速,容错和廉价的基础架构。 最近六个月,我们决定使用我们的 BigData 基础架构,向用户提供有关其应用性能和稳定性的指标,并让他们知道错误如何影响他们的用户群 和收入。 我们知道我们的解决方案应该从第一天开始就可以扩展,因为超过 4%的智能手机将开始使用 DDOS 向我们提供数据。 我们希望能够: * 提取应用程序逻辑并使用 JSON 填充浏览器 * 快速运行复杂算法 * 无需专用 Hadoop 集群即可进行数据实验 * 预处理数据,然后将其存储(减少存储) * 能够在每个节点上处理超过 1000 个并发请求 * 每个应用程序“加入”超过 1.25 亿行 * 做到这一点,而无需花费大量的服务器时间 该解决方案使用: * 在 Azure 上运行的大型实例不到 20 个 * 内存数据库 * 一种用 C 语言编写的功能齐全的自定义 LISP 语言,用于实现查询,这比始终使 VM(带有垃圾收集器)联机的速度快很多倍 * Erlang 用于节点之间的通信 * 修改后的 TCP_TIMEWAIT_LEN 可以惊人地减少 40K 连接,节省了 CPU,内存和 TCP 缓冲区 ## 内存数据库万岁 我们知道,处理所有这些流量的唯一方法是使用内存数据库。 不仅要处理巨大的数据集上的即席问题(例如,“有多少个使用三星设备的唯一用户在一个星期内有此特定错误”), 内存限制还与数据处理前后的数据序列化和反序列化有关。 因此,我们启动了 LDB 项目。 ## LDB 项目 您是否相信可以将来自各种来源(成千上万种不同资源,如移动设备)的数据馈送到系统中,在几行代码中描述要提取的信息,然后将所有这些信息掌握在您的指尖中 ? 实时。 系统持续运行时? LDB 不仅是数据库,更是一个应用程序服务器。 即使是内存中数据,实际上也将数据存储在硬盘驱动器中并在其他节点之间复制。 对于 LDB,我们不会运行查询。 **我们之所以运行算法,是因为我们拥有用 C 语言编写的完整的自定义 LISP 语言,该语言可以访问与数据库**相同的地址空间。 这意味着您可以非常快速地搜索数据,增加计数器,获取/放置等。 拥有 LISP 的优点是,您可以轻松地像 Hive 这样创建类似于 SQL 的语言并实时查询数据,如下所示: ![](https://img.kancloud.cn/e4/86/e486bd33ec3a6924fa7cbd742724cc9b_418x99.png) LDB 的工作方式如下: 每个应用都有自己的 LDB。 这意味着它自己的内存空间。 这样,我们可以轻松地将较大的应用程序(在流量方面)移动到不同的计算机上。 [HTG1] [HTG2] [HTG3] [HTG4] [HTG5] [HTG6] [HTG7] [HTG8] [HTG9]当请求来自移动设备时,主 LDB 节点接受连接(使用 erlang 线程池)并将数据转发到特定的数据库。 此请求处理机制用少于 20 行的 Erlang 代码实现。 我们选择 Erlang 进行节点间通信的另一个原因。 当请求“流式传输”到 LDB 时,名为“ process.lql”的文件负责分析,标记数据并创建任何计数器。 所有这些都是即时完成的,并可满足每个请求。 ![](https://img.kancloud.cn/28/f6/28f67a6e8652d03711712d997ff8959a_696x269.png) 我们能够做到这一点,因为启动 LISP-VM 并针对每个请求执行所有这些过程仍然很多次 始终使 VM(带有垃圾回收器)联机的速度更快。 使用 LDB,我们可以使用不超过 3 行代码来创建时间序列和汇总数据。 例如。 这样会为唯一用户创建 7 天的时间序列: ![](https://img.kancloud.cn/78/cf/78cff1582e871864d027696bc4b05985_470x146.png) ## 备择方案 在我们的测试中,我们发现 SQL 数据库不太适合,因为我们的数据是非结构化的,并且我们需要很多复杂的“联接”(和许多索引)。 另一方面,对于 NoSQL 数据库,我们无法在数据上运行算法(在系统运行时),而使用映射器/约简器会使整个过程变得复杂而缓慢。 我们需要一个没有大锁或 DB 锁的高并发系统,该系统可以在仅几个 KB 的时间内跟踪数百万个唯一事件,并且非常容易扩展。 一个很好的替代方法是使用 Stream 数据库(例如 [Storm](http://storm-project.net/) )。 我们的主要问题是有很多活动部件和单个节点的性能。 使用 LDB,我们的优势是能够非常快速地处理数据(它们驻留在相同的内存空间中),将它们存储为聚合计数器或符号(因此,千兆字节的数据以 KB 为单位),然后让 DSL 执行任何关联 我们要在飞行中。 没有序列化/反序列化,没有网络调用,也没有垃圾收集器。 就像将汇编代码映射到您的数据上一样。 在 LDB 之上,我们还有可以缩放和处理传入数据的接收器,一个流组件,其中的所有内容都在几行代码中定义,一个存储引擎和一个复制 发动机。 ## 优化内核-TCP 的 UDP 行为 与每秒处理大量请求的其他服务相比,进行分析时的独特之处在于,移动设备与服务器之间的对话非常小(3 个 TCP 握手数据包,1 个有效负载数据包和 3 个 TCP 终止数据包 )。 但是,TCP 在设计时并未考虑到类似问题(即设备之间的小对话框),并实现了称为 TIME_WAIT 的状态(持续时间约为 1) 分钟 (在 2.6 Linux 内核中),在该时间之后,最后一个 FIN 数据包发送之后,该特定连接元组的 TCP 状态保持打开状态一段时间,以便接收可能已延迟的任何杂散数据包(即 连接关闭)。 在我们的例子中,这有点没用(我们想要类似于 UDP 行为但具有 TCP 保证的东西),因为有效负载只有 1 个数据包(对于查看请求,最多 4 或 5 个数据包),因此我们决定修改内核源并减少 常量,此常量降至 20 英寸。结果是惊人地减少了 40K 连接,节省了 CPU,内存和 TCP 缓冲区。 我们应用的补丁在文件中: linux-kernel-source / include / net / tcp.h #define TCP_TIMEWAIT_LEN([ 60 * HZ ) 至 #define TCP_TIMEWAIT_LEN( 20 * HZ ) 使用此架构,我们可以为所有付费客户(运行少于 20 个大型实例)提供有关移动应用程序的实时分析和见解。 在 Azure 上,包括后备和备份服务器。 ## 相关文章 * [关于 HackerNews](http://news.ycombinator.com/item?id=4833052) 既然没有垃圾收集器,如何在 LISP 实现中回收内存? 谢谢。 好贴! 我特别喜欢 TCP 技巧。 您能否分享每天有多少事件和多少数据进入? 另外,您要从中提供查询的内存数据集大小是多少? 我对您正在执行的联接大小特别感兴趣。 噢亲爱的。 `tcp_tw_reuse`或`tcp_tw_recycle`有什么问题? 何俊! 我非常喜欢阅读! 我是一位经验丰富的 Erlang 程序员,我很想阅读有关 Lisp 实际使用的更多信息。 如果您有任何有关 List 的良好介绍性文章的链接,那就太好了! 非常感谢您的精彩文章! 本文充满了不寻常的陈述和设计决策,我怀疑 BugSense 是由外星人控制的:) 有什么问题:echo“ 20” > / proc / sys / net / ipv4 / tcp_fin_timeout? 不工作? 在每个请求上启动 LISP VM 的速度要比一直保持 VM 联机的速度快? 好的,我明白了,Lisp VM 不能很好地完成 GC。 但是有一个 JVM 和 Clojure(Lisp 方言顺便说一句) LISP + Erlang 的组合? 有人非常了解 Lisp 和 Erlang :)。 嗯-而不是在服务器上浪费 TCP 时间,您难道不就让客户端在服务器之前关闭 TCP 连接吗? 这将给客户端增加“等待时间”的负担。 我猜您的协议目前已经广泛部署,因此更改它为时已晚? 我愿意在这方面寻找另一面,但是我仍然看不到在提出了如此精美高效的体系结构之后,您选择使用 Windows Azure,这是最糟糕的此类产品(IaaS / PaaS) 。 ..我一直在烦我..这似乎引入了各种性能和财务瓶颈。 除非您对支持 Windows Phone 设备有何需求(极不可能)。 因此,我得出的结论是,您获得了免费优惠或其他优惠。请帮助我理解。 对于建议使用 tcp_tw_reuse 的人: http://serverfault.com/questions/303652/time-wait-connections-not-being-cleaned-up-after-timeout-period-expires tcp_fin_timeout 设置套接字在 FIN-WAIT-2 状态下花费的时间。 此参数不会影响在 TIME_WAIT 状态下花费的时间。 尝试 netstat -o 并观察处于 TIME_WAIT 状态的套接字的计时器值(选择 tcp_fin_timeout 值)。 @Sumit R:你的意思是...? 您是否阅读了整个 serverfault 线程,特别是有关`tcp_tw_reuse`问题的答案? 您实际上曾经使用过`tcp_tw_reuse=1`吗? Lisp 解释器的内存处理由我们完成。 我们使用世代容器,并在每个“简短”脚本完成时回收分配的内存(对于“年轻”条目。由于系统体系结构/设计,无需收集“顽固”条目。通常,我们分为三代) 有自己的收集策略)。 因此,无需拥有成熟的垃圾收集器。 我们不使用 JVM 或任何其他托管 VM 解决方案(Clojure,F#等),因为我们只希望每个 VM(以及特定 VM 上的语言)提供的功能的子集,并且有大量空间可以优化 满足我们自己的“特殊”需求。 此外,Scheme(Lisp)还提供了构建具有表达力的程序所需的一切,这些程序通常具有功能范式的抽象和形式/模式。 你好 真的很想知道有关 Lisp(方案)实现以及它们如何与 Erlang 一起工作的更多信息。 您是否有可能开源示例或框架的一部分? 无论如何,感谢您的文章。 此致 尼古拉斯