提交 3312ced2 编写于 作者: W wizardforcel

2020-06-27 10:09:07

上级 86278fc1
+ [LiveJournal 体系结构](1.md)
+ [mixi.jp 体系结构](2.md)
+ [友谊建筑](3.md)
+ [FeedBurner 体系结构](4.md)
+ [GoogleTalk 架构](5.md)
+ [ThemBid 架构](6.md)
+ [使用 Amazon 服务以 100 美元的价格构建无限可扩展的基础架构](7.md)
+ [TypePad 建筑](8.md)
+ [维基媒体架构](9.md)
+ [Joost 网络架构](10.md)
+ [亚马逊建筑](11.md)
+ [Fotolog 扩展成功的秘诀](12.md)
+ [普恩斯的教训-早期](13.md)
+ [论文:Wikipedia 的站点内部,配置,代码示例和管理问题](14.md)
+ [扩大早期创业规模](15.md)
+ [Feedblendr 架构-使用 EC2 进行扩展](16.md)
+ [Slashdot Architecture-互联网的老人如何学会扩展](17.md)
+ [Flickr 架构](18.md)
+ [Tailrank 架构-了解如何在整个徽标范围内跟踪模因](19.md)
+ [Ruby on Rails 如何在 550k 网页浏览中幸存](20.md)
+ [Mailinator 架构](21.md)
+ [Rackspace 现在如何使用 MapReduce 和 Hadoop 查询 TB 的数据](22.md)
+ [Yandex 架构](23.md)
+ [YouTube 架构](24.md)
+ [Skype 计划 PostgreSQL 扩展到 10 亿用户](25.md)
+ [易趣建筑](26.md)
+ [FaceStat 的祸根与智慧赢得了胜利](27.md)
+ [Flickr 的联合会:每天进行数十亿次查询](28.md)
+ [EVE 在线架构](29.md)
+ [Notify.me 体系结构-同步性](30.md)
+ [Google 架构](31.md)
+ [第二人生架构-网格](32.md)
+ [MySpace 体系结构](33.md)
+ [扩展 Digg 和其他 Web 应用程序](34.md)
+ [Digg 建筑](35.md)
+ [在 Amazon EC2 中部署大规模基础架构的六个经验教训](36.md)
+ [Wolfram | Alpha 建筑](37.md)
+ [为什么 Facebook,Digg 和 Twitter 很难扩展?](38.md)
+ [全球范围扩展的 10 个 eBay 秘密](39.md)
+ [BuddyPoke 如何使用 Google App Engine 在 Facebook 上扩展](40.md)
+ [《 FarmVille》如何扩展以每月收获 7500 万玩家](41.md)
+ [Twitter 计划分析 1000 亿条推文](42.md)
+ [MySpace 如何与 100 万个并发用户一起测试其实时站点](43.md)
+ [FarmVille 如何扩展-后续](44.md)
+ [Justin.tv 的实时视频广播架构](45.md)
+ [策略:缓存 404 在服务器时间上节省了洋葱 66%](46.md)
+ [Poppen.de 建筑](47.md)
+ [MocoSpace Architecture-一个月有 30 亿个移动页面浏览量](48.md)
+ [Sify.com 体系结构-每秒 3900 个请求的门户](49.md)
+ [每月将 Reddit 打造为 2.7 亿页面浏览量时汲取的 7 个教训](50.md)
+ [Playfish 的社交游戏架构-每月有 5000 万用户并且不断增长](51.md)
+ [扩展 BBC iPlayer 的 6 种策略](52.md)
+ [Facebook 的新实时消息系统:HBase 每月可存储 135 亿条消息](53.md)
+ [Pinboard.in Architecture-付费玩以保持系统小巧](54.md)
+ [BankSimple 迷你架构-使用下一代工具链](55.md)
+ [Riak 的 Bitcask-用于快速键/值数据的日志结构哈希表](56.md)
+ [Mollom 体系结构-每秒以 100 个请求杀死超过 3.73 亿个垃圾邮件](57.md)
+ [Wordnik-MongoDB 和 Scala 上每天有 1000 万个 API 请求](58.md)
+ [Node.js 成为堆栈的一部分了吗? SimpleGeo 说是的。](59.md)
+ [堆栈溢出体系结构更新-现在每月有 9500 万页面浏览量](60.md)
+ [Medialets 体系结构-击败艰巨的移动设备数据](61.md)
+ [Facebook 的新实时分析系统:HBase 每天处理 200 亿个事件](62.md)
+ [Microsoft Stack 是否杀死了 MySpace?](63.md)
+ [Viddler Architecture-每天嵌入 700 万个和 1500 Req / Sec 高峰](64.md)
+ [Facebook:用于扩展数十亿条消息的示例规范架构](65.md)
+ [Evernote Architecture-每天有 900 万用户和 1.5 亿个请求](66.md)
+ [TripAdvisor 的短](67.md)
+ [TripAdvisor 架构-4,000 万访客,200M 动态页面浏览,30TB 数据](68.md)
+ [ATMCash 利用虚拟化实现安全性-不变性和还原](69.md)
+ [Google+是使用您也可以使用的工具构建的:闭包,Java Servlet,JavaScript,BigTable,Colossus,快速周转](70.md)
+ [新的文物建筑-每天收集 20 亿多个指标](71.md)
+ [Peecho Architecture-鞋带上的可扩展性](72.md)
+ [标记式架构-扩展到 1 亿用户,1000 台服务器和 50 亿个页面视图](73.md)
+ [论文:Akamai 网络-70 个国家/地区的 61,000 台服务器,1,000 个网络](74.md)
+ [策略:在 S3 或 GitHub 上运行可扩展,可用且廉价的静态站点](75.md)
+ [Pud 是反堆栈-Windows,CFML,Dropbox,Xeround,JungleDisk,ELB](76.md)
+ [用于扩展 Turntable.fm 和 Labmeeting 的数百万用户的 17 种技术](77.md)
+ [StackExchange 体系结构更新-平稳运行,Amazon 4x 更昂贵](78.md)
+ [DataSift 体系结构:每秒进行 120,000 条推文的实时数据挖掘](79.md)
+ [Instagram 架构:1400 万用户,1 TB 的照片,数百个实例,数十种技术](80.md)
+ [PlentyOfFish 更新-每月 60 亿次浏览量和 320 亿张图片](81.md)
+ [Etsy Saga:从筒仓到开心到一个月的浏览量达到数十亿](82.md)
+ [数据范围项目-6PB 存储,500GBytes / sec 顺序 IO,20M IOPS,130TFlops](83.md)
+ [99designs 的设计-数以千万计的综合浏览量](84.md)
+ [Tumblr Architecture-150 亿页面浏览量一个月,比 Twitter 更难扩展](85.md)
+ [Berkeley DB 体系结构-NoSQL 很酷之前的 NoSQL](86.md)
+ [Pixable Architecture-每天对 2000 万张照片进行爬网,分析和排名](87.md)
+ [LinkedIn:使用 Databus 创建低延迟更改数据捕获系统](88.md)
+ [在 30 分钟内进行 7 年的 YouTube 可扩展性课程](89.md)
+ [YouPorn-每天定位 2 亿次观看](90.md)
+ [Instagram 架构更新:Instagram 有何新功能?](91.md)
+ [搜索技术剖析:blekko 的 NoSQL 数据库](92.md)
+ [Pinterest 体系结构更新-1800 万访问者,增长 10 倍,拥有 12 名员工,410 TB 数据](93.md)
+ [搜索技术剖析:使用组合器爬行](94.md)
+ [iDoneThis-从头开始扩展基于电子邮件的应用程序](95.md)
+ [StubHub 体系结构:全球最大的票务市场背后的惊人复杂性](96.md)
+ [FictionPress:在网络上发布 600 万本小说](97.md)
+ [Cinchcast 体系结构-每天产生 1,500 小时的音频](98.md)
+ [棱柱架构-使用社交网络上的机器学习来弄清您应该在网络上阅读的内容](99.md)
+ [棱镜更新:基于文档和用户的机器学习](100.md)
+ [Zoosk-实时通信背后的工程](101.md)
+ [WordPress.com 使用 NGINX 服务 70,000 req / sec 和超过 15 Gbit / sec 的流量](102.md)
+ [史诗般的 TripAdvisor 更新:为什么不在云上运行? 盛大的实验](103.md)
+ [UltraDNS 如何处理数十万个区域和数千万条记录](104.md)
+ [更简单,更便宜,更快:Playtomic 从.NET 迁移到 Node 和 Heroku](105.md)
+ [Spanner-关于程序员使用 NoSQL 规模的 SQL 语义构建应用程序](106.md)
+ [BigData 使用 Erlang,C 和 Lisp 对抗移动数据海啸](107.md)
+ [分析数十亿笔信用卡交易并在云中提供低延迟的见解](108.md)
+ [MongoDB 和 GridFS 用于内部和内部数据中心数据复制](109.md)
+ [每天处理 1 亿个像素-少量竞争会导致大规模问题](110.md)
+ [DuckDuckGo 体系结构-每天进行 100 万次深度搜索并不断增长](111.md)
+ [SongPop 在 GAE 上可扩展至 100 万活跃用户,表明 PaaS 未通过](112.md)
+ [Iron.io 从 Ruby 迁移到 Go:减少了 28 台服务器并避免了巨大的 Clusterf ** ks](113.md)
+ [可汗学院支票簿每月在 GAE 上扩展至 600 万用户](114.md)
+ [在破坏之前先检查自己-鳄梨的建筑演进的 5 个早期阶段](115.md)
+ [缩放 Pinterest-两年内每月从 0 到十亿的页面浏览量](116.md)
+ [Facebook 的网络秘密](117.md)
+ [神话:埃里克·布鲁尔(Eric Brewer)谈银行为什么不是碱-可用性就是收入](118.md)
+ [一千万个并发连接的秘密-内核是问题,而不是解决方案](119.md)
+ [GOV.UK-不是你父亲的书库](120.md)
+ [缩放邮箱-在 6 周内从 0 到 100 万用户,每天 1 亿条消息](121.md)
+ [在 Yelp 上利用云计算-每月访问量为 1.02 亿,评论量为 3900 万](122.md)
+ [每台服务器将 PHP 扩展到 30,000 个并发用户的 5 条 Rockin'Tips](123.md)
+ [Twitter 的架构用于在 5 秒内处理 1.5 亿活跃用户,300K QPS,22 MB / S Firehose 以及发送推文](124.md)
+ [Salesforce Architecture-他们每天如何处理 13 亿笔交易](125.md)
+ [扩大流量的设计决策](126.md)
+ [ESPN 的架构规模-每秒以 100,000 Duh Nuh Nuhs 运行](127.md)
+ [如何制作无限可扩展的关系数据库管理系统(RDBMS)](128.md)
+ [Bazaarvoice 的架构每月发展到 500M 唯一用户](129.md)
+ [HipChat 如何使用 ElasticSearch 和 Redis 存储和索引数十亿条消息](130.md)
+ [NYTimes 架构:无头,无主控,无单点故障](131.md)
+ [接下来的大型声音如何使用 Hadoop 数据版本控制系统跟踪万亿首歌曲的播放,喜欢和更多内容](132.md)
+ [Google 如何备份 Internet 和数十亿字节的其他数据](133.md)
+ [从 HackerEarth 用 Apache 扩展 Python 和 Django 的 13 个简单技巧](134.md)
+ [AOL.com 体系结构如何发展到 99.999%的可用性,每天 800 万的访问者和每秒 200,000 个请求](135.md)
+ [Facebook 以 190 亿美元的价格收购了 WhatsApp 体系结构](136.md)
+ [使用 AWS,Scala,Akka,Play,MongoDB 和 Elasticsearch 构建社交音乐服务](137.md)
+ [大,小,热还是冷-条带,Tapad,Etsy 和 Square 的健壮数据管道示例](138.md)
+ [WhatsApp 如何每秒吸引近 5 亿用户,11,000 内核和 7,000 万条消息](139.md)
+ [Disqus 如何以每秒 165K 的消息和小于 0.2 秒的延迟进行实时处理](140.md)
+ [关于 Disqus 的更新:它仍然是实时的,但是 Go 摧毁了 Python](141.md)
+ [关于 Wayback 机器如何在银河系中存储比明星更多的页面的简短说明](142.md)
+ [在 PagerDuty 迁移到 EC2 中的 XtraDB 群集](143.md)
+ [扩展世界杯-Gambify 如何与 2 人组成的团队一起运行大型移动投注应用程序](144.md)
+ [一点点:建立一个可处理每月 60 亿次点击的分布式系统的经验教训](145.md)
+ [StackOverflow 更新:一个月有 5.6 亿次网页浏览,25 台服务器,而这一切都与性能有关](146.md)
+ [Tumblr:哈希处理每秒 23,000 个博客请求的方式](147.md)
+ [使用 HAProxy,PHP,Redis 和 MySQL 处理 10 亿个请求的简便方法来构建成长型启动架构](148.md)
+ [MixRadio 体系结构-兼顾各种服务](149.md)
+ [Twitter 如何使用 Redis 进行扩展-105TB RAM,39MM QPS,10,000 多个实例](150.md)
+ [正确处理事情:通过即时重放查看集中式系统与分散式系统](151.md)
+ [Instagram 提高了其应用程序的性能。 这是如何做。](152.md)
+ [Clay.io 如何使用 AWS,Docker,HAProxy 和 Lots 建立其 10 倍架构](153.md)
+ [英雄联盟如何将聊天扩大到 7000 万玩家-需要很多小兵。](154.md)
+ [Wix 的 Nifty Architecture 技巧-大规模构建发布平台](155.md)
+ [Aeron:我们真的需要另一个消息传递系统吗?](156.md)
+ [机器:惠普基于忆阻器的新型数据中心规模计算机-一切仍在变化](157.md)
+ [AWS 的惊人规模及其对云的未来意味着什么](158.md)
+ [Vinted 体系结构:每天部署数百次,以保持繁忙的门户稳定](159.md)
+ [将 Kim Kardashian 扩展到 1 亿个页面](160.md)
+ [HappyPancake:建立简单可扩展基金会的回顾](161.md)
+ [阿尔及利亚分布式搜索网络的体系结构](162.md)
+ [AppLovin:通过每天处理 300 亿个请求向全球移动消费者进行营销](163.md)
+ [Swiftype 如何以及为何从 EC2 迁移到真实硬件](164.md)
+ [我们如何扩展 VividCortex 的后端系统](165.md)
+ [Appknox 架构-从 AWS 切换到 Google Cloud](166.md)
+ [阿尔及利亚通往全球 API 的愤怒之路](167.md)
+ [阿尔及利亚通往全球 API 步骤的愤怒之路第 2 部分](168.md)
+ [为社交产品设计后端](169.md)
+ [阿尔及利亚通往全球 API 第 3 部分的愤怒之路](170.md)
+ [Google 如何创造只有他们才能创造的惊人的数据中心网络](171.md)
+ [Autodesk 如何在 Mesos 上实施可扩展事件](172.md)
+ [构建全球分布式,关键任务应用程序:Trenches 部分的经验教训 1](173.md)
+ [构建全球分布式,关键任务应用程序:Trenches 第 2 部分的经验教训](174.md)
+ [需要物联网吗? 这是美国一家主要公用事业公司从 550 万米以上收集电力数据的方式](175.md)
+ [Uber 如何扩展其实时市场平台](176.md)
+ [优步变得非常规:使用司机电话作为备份数据中心](177.md)
+ [在不到五分钟的时间里,Facebook 如何告诉您的朋友您在灾难中很安全](178.md)
+ [Zappos 的网站与 Amazon 集成后冻结了两年](179.md)
+ [为在现代时代构建可扩展的有状态服务提供依据](180.md)
+ [细分:使用 Docker,ECS 和 Terraform 重建基础架构](181.md)
+ [十年 IT 失败的五个教训](182.md)
+ [Shopify 如何扩展以处理来自 Kanye West 和 Superbowl 的 Flash 销售](183.md)
+ [整个 Netflix 堆栈的 360 度视图](184.md)
+ [Wistia 如何每小时处理数百万个请求并处理丰富的视频分析](185.md)
+ [Google 和 eBay 关于构建微服务生态系统的深刻教训](186.md)
+ [无服务器启动-服务器崩溃!](187.md)
+ [在 Amazon AWS 上扩展至 1100 万以上用户的入门指南](188.md)
+ [为 David Guetta 建立无限可扩展的在线录制活动](189.md)
+ [Tinder:最大的推荐引擎之一如何决定您接下来会看到谁?](190.md)
+ [如何使用微服务建立财产管理系统集成](191.md)
+ [Egnyte 体系结构:构建和扩展多 PB 分布式系统的经验教训](192.md)
+ [Zapier 如何自动化数十亿个工作流自动化任务的旅程](193.md)
+ [Jeff Dean 在 Google 进行大规模深度学习](194.md)
+ [如今 Etsy 的架构是什么样的?](195.md)
+ [我们如何在 Mail.Ru Cloud 中实现视频播放器](196.md)
+ [Twitter 如何每秒处理 3,000 张图像](197.md)
+ [每天可处理数百万个请求的图像优化技术](198.md)
+ [Facebook 如何向 80 万同时观看者直播](199.md)
+ [Google 如何针对行星级基础设施进行行星级工程设计?](200.md)
+ [为 Mail.Ru Group 的电子邮件服务实施反垃圾邮件的猫捉老鼠的故事,以及 Tarantool 与此相关的内容](201.md)
+ [The Dollar Shave Club Architecture Unilever 以 10 亿美元的价格被收购](202.md)
+ [Uber 如何使用 Mesos 和 Cassandra 跨多个数据中心每秒管理一百万个写入](203.md)
+ [从将 Uber 扩展到 2000 名工程师,1000 个服务和 8000 个 Git 存储库获得的经验教训](204.md)
+ [QuickBooks 平台](205.md)
+ [美国大选期间城市飞艇如何扩展到 25 亿个通知](206.md)
+ [Probot 的体系结构-我的 Slack 和 Messenger Bot 用于回答问题](207.md)
+ [AdStage 从 Heroku 迁移到 AWS](208.md)
+ [为何将 Morningstar 迁移到云端:降低 97%的成本](209.md)
+ [ButterCMS 体系结构:关键任务 API 每月可处理数百万个请求](210.md)
+ [Netflix:按下 Play 会发生什么?](211.md)
+ [ipdata 如何以每月 150 美元的价格为来自 10 个无限扩展的全球端点的 2500 万个 API 调用提供服务](212.md)
+ [每天为 1000 亿个事件赋予意义-Teads 的 Analytics(分析)管道](213.md)
+ [Auth0 体系结构:在多个云提供商和地区中运行](214.md)
+ [从裸机到 Kubernetes](215.md)
+ [Egnyte Architecture:构建和扩展多 PB 内容平台的经验教训](216.md)
+ [缩放原理](217.md)
+ [TripleLift 如何建立 Adtech 数据管道每天处理数十亿个事件](218.md)
+ [Tinder:最大的推荐引擎之一如何决定您接下来会看到谁?](219.md)
+ [如何使用微服务建立财产管理系统集成](220.md)
+ [Egnyte 体系结构:构建和扩展多 PB 分布式系统的经验教训](221.md)
+ [Zapier 如何自动化数十亿个工作流自动化任务的旅程](222.md)
+ [Jeff Dean 在 Google 进行大规模深度学习](223.md)
+ [如今 Etsy 的架构是什么样的?](224.md)
+ [我们如何在 Mail.Ru Cloud 中实现视频播放器](225.md)
+ [Twitter 如何每秒处理 3,000 张图像](226.md)
+ [每天可处理数百万个请求的图像优化技术](227.md)
+ [Facebook 如何向 80 万同时观看者直播](228.md)
+ [Google 如何针对行星级基础设施进行行星级工程设计?](229.md)
+ [为 Mail.Ru Group 的电子邮件服务实施反垃圾邮件的猫捉老鼠的故事,以及 Tarantool 与此相关的内容](230.md)
+ [The Dollar Shave Club Architecture Unilever 以 10 亿美元的价格被收购](231.md)
+ [Uber 如何使用 Mesos 和 Cassandra 跨多个数据中心每秒管理一百万个写入](232.md)
+ [从将 Uber 扩展到 2000 名工程师,1000 个服务和 8000 个 Git 存储库获得的经验教训](233.md)
+ [QuickBooks 平台](234.md)
+ [美国大选期间城市飞艇如何扩展到 25 亿条通知](235.md)
+ [Probot 的体系结构-我的 Slack 和 Messenger Bot 用于回答问题](236.md)
+ [AdStage 从 Heroku 迁移到 AWS](237.md)
+ [为何将 Morningstar 迁移到云端:降低 97%的成本](238.md)
+ [ButterCMS 体系结构:关键任务 API 每月可处理数百万个请求](239.md)
+ [Netflix:按下 Play 会发生什么?](240.md)
+ [ipdata 如何以每月 150 美元的价格为来自 10 个无限扩展的全球端点的 2500 万个 API 调用提供服务](241.md)
+ [每天为 1000 亿个事件赋予意义-Teads 的 Analytics(分析)管道](242.md)
+ [Auth0 体系结构:在多个云提供商和地区中运行](243.md)
+ [从裸机到 Kubernetes](244.md)
+ [Egnyte Architecture:构建和扩展多 PB 内容平台的经验教训](245.md)
# AdStage 从 Heroku 迁移到 AWS
# Joost 网络架构
> 原文: [http://highscalability.com/blog/2017/5/1/the-adstage-migration-from-heroku-to-aws.html](http://highscalability.com/blog/2017/5/1/the-adstage-migration-from-heroku-to-aws.html)
> 原文: [http://highscalability.com/blog/2007/9/7/joost-network-architecture.html](http://highscalability.com/blog/2007/9/7/joost-network-architecture.html)
![](img/222acfea60c08f75dd8f5c824f121167.png)
Joost 的网络架构师 Colm MacCarthaigh 在 2007 年 4 月 3 日于曼彻斯特举行的英国网络运营商论坛会议上向[做了本次演讲](http://www.uknof.org.uk/uknof7/MacCarthaigh-Joost.pdf)
*这是 AdStage 网站可靠性工程负责人 [G Gordon Worley III](https://www.linkedin.com/in/gworley3/) 的来宾[重新发布](https://medium.com/adstage-engineering/migrating-from-heroku-to-aws-our-story-80084d31025e)。*
我没有在上面的文章中看到链接。 但是我有 [http://www.royans.net/files/MacCarthaigh-Joost.pdf](<a rel=)
“ >这里有一个副本 [http://www.royans.net/files /MacCarthaigh-Joost.pdf](http://www.royans.net/files/MacCarthaigh-Joost.pdf)
我在 2013 年秋季加入 [AdStage](https://medium.com/@adstage) 时,我们已经在 Heroku 上运行了。 这是显而易见的选择:超级容易上手,比全尺寸虚拟服务器便宜,并且足够灵活以随着我们的业务发展。 成长,我们做到了。 Heroku 让我们仅专注于构建引人注目的产品,而不会分散管理基础结构,因此,到 2015 年末,我们已同时运行数千个 dynos(容器)以跟上我们的客户
我在 Joost 论坛上链接了 Colm 的演示视频
我们需要所有这些测功机,因为在后端,我们看起来很像[细分](https://medium.com/@segment),并且像它们一样,我们的许多成本[与用户数量](https://segment.com/blog/the-million-dollar-eng-problem/)成线性比例。 以 25 美元/ dyno /月的价格计算,加上其他技术成本,到 2016 年中期,我们的年度基础设施支出将突破 100 万美元,而这占了 COGS 的很大比例,因此要花费数年才能实现盈利。 坦率地说,这种情况是不可持续的。 工程团队开会讨论了我们的选择,一些快速计算表明我们为 Heroku 的便利每月要支付超过 10,000 美元,而类似资源将直接在 AWS 上花费。 如果我们从 Heroku 迁移,那足以证明工程师专职在基础架构上工作,因此我的任务是成为我们的第一位运营负责人,并带头进行向 AWS 的迁移。
[http://www.scaryideas.com/video/2362/](http://www.scaryideas.com/video/2362/)
这也是一个很好的时机,因为 Heroku 已成为我们最大的限制。 我们的工程团队采用了[看板](https://en.wikipedia.org/wiki/Kanban_%28development%29)方法,因此理想情况下,我们会不断产生从构思到完成的故事。 不过,当时我们正在生成大量正在进行的工作,这些工作通常会阻塞我们的发布渠道。 进行质量检查的工作很慢,并且经常被送回以进行错误修复。 “ [在我的计算机](https://jcooney.net/archive/2007/02/01/42999.aspx)上正常工作”的情况经常出现,但是当暴露在我们的暂存环境中时会失败。 由于 AdStage 是写在不同技术堆栈上的相互依赖的服务的复杂组合,因此每个开发人员都很难使其工作站与生产保持最新状态,这也使得部署到分阶段和生产过程很缓慢,需要大量的人工干预 。 但是,我们在此问题上别无选择,因为我们不得不将每个服务都部署为自己的 Heroku 应用程序,从而限制了自动化的机会。 我们迫切需要找到一种替代方法,使我们能够自动化部署并为开发人员提供更早的访问可靠测试环境的机会。
因此,除了通过迁移 Heroku 削减成本外,我们还需要清除质量检查约束。 否则,我可以自由地设计我们的 AWS 部署,只要它以最少的代码更改即可运行我们所有的现有服务,但我添加了一些需求:
* **简单的系统管理** :我以前使用过 Chef 等工具,并希望避免从头开始频繁重建系统的容易出错的过程。 我想通过登录机器并运行命令来更新机器。
* **无聊** :我想使用已知有效的“无聊”技术,而不是尝试一些新技术来解决其问题。 我想将风险集中在业务逻辑而不是基础架构中。
* **零停机时间** :在 Heroku 上进行部署往往会导致我们的用户遇到“漏洞”,原因是某些用户请求花费的运行时间比 Heroku 允许的连接耗用时间更长。 我希望能够消除这些斑点。
* **回滚** :如果部署出现问题,我希望能够退出部署并使用最新的已知工作版本恢复服务。
* **有限的复杂度** :我将是唯一一个专职构建和维护我们的基础架构的人,因此我需要确定项目的范围以适应需求。
知道 [Netflix](https://medium.com/@NetflixTechBlog) [设法通过](http://highscalability.com/blog/2015/11/9/a-360-degree-view-of-the-entire-netflix-stack.html)[在 AWS 上运行](http://techblog.netflix.com/2013/03/ami-creation-with-aminator.html)数十亿美元的业务,没有比亚马逊的机器映像和自动缩放组更完美,我决定遵循他们的可靠方法,但绝对没有 意味着“性感”的方法:构建机器映像,使用它在自动伸缩组中创建实例,将其放在弹性负载均衡器之后,并将负载均衡器连接到 DNS 记录,以使我们的客户以及彼此可以访问它们。
因此,我着手构建我们的 AWS 部署策略。
### 成为 AWS Sumo
在对系统进行工程设计时,我喜欢花很多时间在进行设计之前先仔细考虑并测试假设。 Rich Hickey 将此称为[吊床驱动的开发](https://www.youtube.com/watch?v=f84n5oFoZBc)
我们的办公室没有吊床,所以我使用了[相扑躺椅](https://www.sumolounge.com/)
![](img/8e7035455cd1d066981cf95862e69d34.png)
在 2016 年春季的几个月中,我思考并思考并整理了 AWS 部署系统的基础。 它的架构看起来像这样:
![](img/0c10e55ee443acef0a7f6bd72b5472bf.png)
它的核心是我们所谓的 AdStage 统一图片。 此机器映像用于为所有环境(从开发和测试到过渡和生产)中的所有服务创建实例。 它上面是我们所有存储库的副本以及运行它们所需的依赖项。 根据一些实例标签的值,实例可以以不同的方式出现以反映其用法。
例如,当一个实例以“审阅”模式出现时,所有服务及其从属数据库在该实例上一起运行并相互通信。 这样,进行开发和质量检查的工程师就可以访问运行任意代码版本的完整堆栈的隔离版本。 他们在这些评论框上所做的任何操作都不会影响登台或制作,也不会与其他评论框进行交互,从而完全消除了我们以前的质量检查/登台限制。 另外,只要审核框通过质量检查,就可以对其进行成像,并将该图像部署到生产中。
之所以可行,是因为当实例以“登台”或“生产”模式启动时,它还会告知其应运行的服务。 这是由实例从其自动伸缩组继承的标签确定的,这使我们可以启动运行相同代码的实例队列,以分散客户的负载。 对于服务于 Web 请求的自动扩展组,它们连接到弹性负载均衡器,该负载均衡器在我们的服务器之间平均分配请求。 负载平衡器为我们提供了一个固定点,我们可以在该固定点上平稳地交换实例,从而实现零停机时间部署,并使回滚就像将旧版本的统一映像保留在备用数据库中一样容易交换。
但是,我们使用的 AWS 资源无法完全协调自身,因此我们编写了一个使用 AWS API 来实现的 Ruby [Thor](https://github.com/erikhuda/thor) 应用程序。 它负责启动审阅框,构建映像,然后将这些映像部署到暂存和生产环境中。 它会在将负载均衡器切换到新版本之前自动验证部署是否正常运行,如果部署完成后检测到问题,则会建议回滚。 它还使用一些巧妙的技巧来协调多个部署并锁定关键资源,以防止多个工程师破坏彼此的部署,因此任何人都可以启动部署,尽管如果这会引起冲突,他们将被停止。
这涵盖了我们的所有需求:成像实例使系统管理变得容易,设置很无聊且被广泛使用,部署过程固有的停机时间为零,支持回滚的部署是自动化的,并且在少于 1500 的情况下并不是很复杂 而且,由于它解决了 QA 约束,并且据我们估计将节省 10,000 美元的运营支出,因此剩下的只是计划从 Heroku 到 AWS 的实时迁移。
### 实时迁移
2016 年 7 月是旧金山的典型节日。 大部分时间,雾气和寒冷的空气使我一直在里面工作,而在我们办公室对面的街道上,准备不足的游客在[龙门](https://www.lonelyplanet.com/usa/san-francisco/attractions/dragons-gate/a/poi-sig/383985/361858)上自拍时发抖。 同样,因为一切都准备从 Heroku 迁移到 AWS,所以我们要做很多工作。
我们的客户依靠我们来管理他们的广告活动,自动化他们的广告支出并报告他们的广告效果。 当我们陷入困境时,它们又陷入了直接通过网络界面手动创建和更新广告的黑暗时代。 当我们切换到 AWS 时,他们负担不起我们离线的费用,因此我们将不得不进行实时迁移。 或至少与合理生活一样。
我们实施了 1 周的代码冻结,并在星期六的早晨找到了 1 小时的窗口,那时我切换了数据库和其他在运行时不易移动的服务,而 AdStage 进入维护模式。 在准备过程中,我们已经进行了登台系统的迁移,并编写了一部剧本,可以用来削减生产。 我使用代码冻结功能花了一周时间来调整 AWS 部署以匹配 Heroku 部署。 周六上午一切似乎都很好。 我们失败了,我切断了数据库,然后重新启动了 AdStage。 我花了整整一天的时间看监视器,并靠近键盘,以防万一发生任何问题,但是什么也没做。 那天晚上我睡着了,以为一切都很好。
在一个 la 懒的星期天早晨之后,我开始在下午收到一些警报,提示我们的进口商正在备份。 当我们研究该问题时,问题很快就变得显而易见:尽管名义上拥有更多的计算资源,但在某种程度上,我们在 AWS 上的 CPU 数量要少于 Heroku。 结果,我们无法跟上,并且每小时我们都越来越落后。 为了避免队列溢出,我们不得不降低导入的频率,最终我们不得不重新打开 Heroku 应用程序以与 AWS 一起运行以跟上工作量。 这与省钱相反。
我们发现,Heroku 一直在告诉我们一个幸福的谎言。 官方每个 dyno 仅获得 2 个 [ECU](https://aws.amazon.com/ec2/faqs/#What_is_an_EC2_Compute_Unit_and_why_did_you_introduce_it) ,但实际情况是,由于我们 Heroku 上的邻居没有充分利用它们的全部份额,我们接近了 6 个。 这意味着我们的 AWS 实例数量太小了 3 倍,尽管 Heroku 实际上便宜得多! 如果只有一种方法可以为更多实例支付更少的费用……
那就是我们开始使用竞价型实例的时候。 我们曾考虑过使用它们,因为它们的价格约为按需价格的 1/10,但是它们存在一定的风险,因为如果您的底价低于拍卖价,它们可以随时终止。 幸运的是,这种情况很少发生,否则自动伸缩组会为您管理点实例的复杂性。 另外,如果备份临时扩展组使用按需部署的按需实例,则很容易,如果我们暂时无法获得足够的竞价型实例来满足需求,则可以通过单个命令进行扩展。 我们最终能够将约 80%的机队转换为现场实例,尽管使用的资源比原始预期多了 3 倍,但我们的成本却降低到了预期目标之内。
### 结论
除了我们对容量的意外低估外,从 Heroku 切换到 AWS 的过程也很顺利。 不过请不要误会我的意思:这是值得做的,因为我们已经达到了将我们的一些基础设施运营纳入内部的经济规模才有意义。 如果我们不花至少一名工程师的薪水来购买可以通过转用 AWS 节省的运营成本,并且如果基础架构没有成为核心能力,那么我们将坚持使用 Heroku 并让那个人(我!)来工​​作 在对我们的业务更重要的事情上。 只是由于经济和流程的变化,从 Heroku 迁移到 AWS 成为了我们的故事的一部分。
Heroku 在 AWS 上运行,因此您不必进行过多的迁移就可以减少中间商。
...或者您雇用知道如何正确运行数据中心的人员。
感谢您的帖子。 非常有趣,只是有几个问题:图像如何获得其初始配置? 您提到要避免使用 Chef / Puppet 之类的东西,但是大概您仍然需要一些可重复的过程来使用初始配置来构建 AMI。 那是雷神应用程序的功能吗?
您应该尝试进行性能调整,例如 JVM 调整,线程池调整等,以降低基础架构成本。
似乎没有这么多麻烦就节省了很多。 您节省了全职人员成本,但是在 AWS 上通常需要 DevOps 成本,在 Heroku 中,Dev 团队可以解决。 放大/缩小测功机与 EC2 相比,哪一个更容易?
\ No newline at end of file
幻灯片是一样的。
\ No newline at end of file
# Tumblr:哈希处理每秒 23,000 个博客请求的方式
# 棱镜更新:基于文档和用户的机器学习
> 原文: [http://highscalability.com/blog/2014/8/4/tumblr-hashing-your-way-to-handling-23000-blog-requests-per.html](http://highscalability.com/blog/2014/8/4/tumblr-hashing-your-way-to-handling-23000-blog-requests-per.html)
> 原文: [http://highscalability.com/blog/2012/8/1/prismatic-update-machine-learning-on-documents-and-users.html](http://highscalability.com/blog/2012/8/1/prismatic-update-machine-learning-on-documents-and-users.html)
![](img/b53e7c03eb181dee4f3635b07ef4a84e.png)
![](img/70ac891b8ff6179d45189f15eaa4af67.png)
*这是 Tumblr 的 SRE 工程师 [](http://michael.tumblr.com/) [Michael Schenck](http://michael.tumblr.com/) 的特邀帖子。*
[Prismatic Architecture-使用社交网络上的机器学习确定您应该在网络上阅读的内容](http://highscalability.com/blog/2012/7/30/prismatic-architecture-using-machine-learning-on-social-netw.html)的同时,Jason Wolfe 甚至面对漫长的夜晚将 iPhone 应用程序投入使用而感到疲倦的感觉, 英勇地同意谈论 Primatic 的机器学习方法。
在 Tumblr,博客(或 Tumblelog)是我们互联网上访问量最高的面孔之一。 tumblelogs 最方便的方面之一是其高度可缓存的特性,这是奇妙的,因为 Tumblr 网络为我们的用户提供了很高的视图/发布比率。 就是说,扩展边界代理层(更不用说缓存层)对满足所有这些请求是必需的,这并非完全简单。
文档和用户是 Prismatic 应用 ML(机器学习)的两个领域:
本文介绍了负责博客服务的外围部分的体系结构,这是我们流量更大的外围端点之一。
### 文件 ML
这是我们的方法。
* 给定一个 HTML 文档:
* 了解如何提取页面的主要文本(而不是侧边栏,页脚,注释等),标题,作者,最佳图像等
* 确定相关功能(例如,文章的主题,主题等)
* 其中大多数任务的设置非常典型。 使用其他机器上的大批作业对模型进行训练,这些机器从 s3 读取数据,将学习到的参数文件保存到 s3,然后在摄取管道中从 s3 读取(并定期刷新)模型。
* 流出系统的所有数据都可以反馈到该管道中,这有助于了解更多有趣的内容,并随着时间的推移从错误中学习。
* 从软件工程的角度来看,Prismatic 编写的最有趣的框架之一是“ flop”库,该库实现了最先进的 ML 训练和推理代码,看起来与精美的普通 Clojure 代码非常相似,但是可以编译(使用 宏的魔力)到低级数组操作循环,这些循环与 Java 一样接近金属而无需借助 JNI。
* 与相应的 Java 相比,该代码可以紧凑和易于阅读,并且执行速度基本相同。
* 创建[快速运行的故事聚类组件](http://blog.getprismatic.com/blog/2012/4/17/clustering-related-stories.html)付出了很多努力。
### 统计信息
### 用户 ML
* 共有 278 名员工,团队中有 6 名员工负责 Tumblr 的所有外围(Perimeter-SRE),包括一名经理。
* 超过 2800 台服务器中,不到 20%的服务器用于博客服务功能
* 每秒(峰值)超过 23,000 个博客请求
* 每秒(峰值)超过 6,500 个博客缓存清除事件
* 超过 1.96 亿个博客
* 超过 930 亿个帖子
### 平台
* [HAProxy](http://www.haproxy.org/)
* [清漆](https://www.varnish-cache.org/)
* [](http://bird.network.cz/)
### 我们在哪里-基于地图的分区
在早期,我们只需要一台活动和一台备用代理服务器以及清漆节点。 两者都很容易管理,监视和高度可用。
但是,由于要满足所有用户请求,因此将达到容量限制,并且由于流行而导致停机前,必须准备好下一步步骤(即使不是理想的部署)。
### 超出单个代理节点
超出单个 活动 代理服务器的数量非常普遍,并且通常涉及 DNS。 像循环 A 记录这样基本的东西可能会满足您的需求,但通常值得花额外的钱进行健康检查 GSLB 配置(即使您只有一个地理位置)。
DNS 的缺点是,尽管名称服务器将以相当均匀的速率对每个 IP 进行响应,但不能保证每个查找都将用于相同数量的请求。 用户 A 可能在一分钟内向解析的 IP 发出 10 个请求,而机器人 B 可能在同一分钟内发出 100 个请求。 如果您有两个 IP,则用户 A 获得一个 IP,而机器人 B 获得另一个 IP,而它们是仅有的两个发出请求的客户端,那么您的一个代理的请求速率是另一个的 10 倍。
较低的 TTL 可以减轻此影响,以便 30 秒 TTL 可以平衡两个代理之间的那 110 个请求。 在最初的 30 秒内,用户 A 将转到代理 P1,而机器人 B 将转到代理 P2。 然后,他们的下一个解决方案可能会交换 IP,以便用户 A 将其请求发送到代理 P2,而机器人 B 将其请求发送到代理 P1。 在该分钟窗口结束时,每个代理将处理大约 60 个请求。 TTL 较低的缺点是查找更多,因此 DNS 成本较高(但 DNS 通常是您较便宜的第三方服务之一)。
### 超出单个清漆节点
虽然 DNS 可以为您增加代理层的时间,但是缩放清漆要复杂一些。 即使您使用单个清漆节点的容量限制围绕请求并发进行,您也不希望简单地在循环中添加两个清漆节点。 这降低了缓存命中率,清除了更多的资源/时间,并且实际上并没有增加缓存的工作量(仅复制它)。
超出单个清漆节点的最简单迭代是 静态分区 。 这涉及确定您的唯一标识符,并在两个清漆节点之间划分此空间。
对于 Tumblelogs,这是博客的主机名。 由于 DNS 不区分大小写,因此您只需要担心 40 个字符即可。 字母数字(a-z 和 0-9)和四个允许的字符(-_。〜)。 因此,对于两个清漆节点,博客主机名在这两个缓存节点之间被分割(在第一个字符上)。
### 均匀分布的分区-通过一致的哈希
前面的两个示例(DNS 循环和静态分区)都是朝着正确方向迈出的一步,但是在分区方面却提供了非常粗糙的粒度。 在足够小的规模上,这种粒度不一定是有问题的,但是随着您的流量开始增长,方差变得更加明显。 结果,减少最不热和最热节点处理的流量差异变得越来越重要。 这就是一致性哈希真正可以发挥作用的地方。
### 分区代理流量
如果您的服务器所处的环境可以影响服务器前面的路由器,用户和代理服务器之间的路由器的路由表,那么您可以利用等价的多 -路径路由(ECMP)。 ECMP 使您能够将代理视为同一哈希环中的多个切片,然后在这些切片之间映射请求者。
这是通过通知到特定目标 IP(高可用性 IP)的多个路径(代理服务器)的路由基础结构来实现的。 然后,ECMP 将对请求源进行哈希处理,以确定哪个代理应接收此请求会话的数据包。 典型的 ECMP 实现提供第 3 层(仅 IP)和第 3 + 4 层(IP:端口)哈希选项。 第 3 层意味着来自特定 IP 的所有请求将转到特定的代理,这可能有助于调试,但与使用单个 NAT IP 的大型网络不平衡。 第 3 + 4 层通常提供最佳的分发,但是调试特定的客户端变得更具挑战性。
有多种方法可以 通知 路由器多个路径,但是我建议使用 OSPF 或 iBGP 进行动态路由通告。 一个人只需要在环回接口上侦听高度可用的 IP,启用内部路由以及将自己的 IP 作为下一跃点广告到该高度可用的 IP。 我们发现 BIRD 提供了一种轻巧可靠的方式来执行来自代理的路由广告。
### 划分清漆流量
Tumblelog 通过其完全限定的域名(FQDN)进行标识,因此,博客的所有 URI 路径将始终在该博客 FQDN 下找到。 Tumblelog 的大部分是 tumblr.com 的子域,例如 [engineering.tumblr.com](http://engineering.tumblr.com/) ,但是我们也支持用户携带自己的自定义域名 。
考虑各种 FQDN 时,很明显,TLD 的变体数量最少,然后是域名(特别是由于绝大多数是 tumblr.com),然后是子域。 因此,我们最重要的位出现在可变长度字符串的最左侧。
### 了解问题域
![](img/acbf9820b55f36b5e6df32353fdd183a.png)
* 完美-演示将散列函数应用于我们的测试数据集时,其散列函数是否为 完美
* constant_hdr-主机标头上的一致性哈希(最佳现实结果)
* constant_hdr_use_domain_only-基本域名(即 tumblr.com 或 foo.net)上的一致性哈希,只有两个阵营 tumblr.com 和所有其他域名
* mapbased_firstchar-将主机标头的第一个字符映射到清漆节点(我们的原始静态分区实现)
* mapbased_hdr-基于主机标头的映射
虽然一致的散列显然是 tumblelog FQDN 的最平均分布的领先者,但是我们接着确定散列函数是否合适。 默认情况下,HAProxy 使用 SDBM 哈希函数。 但是,在进一步研究后,通过比较 SDBM,CRC,MD5,DJB2 等,我们确定 DJB2 提供了更好的分布。 这导致我们向 HAProxy 提交了补丁,以使哈希函数可配置(有关更多信息,请参见“感谢”部分)。
### 比较静态分区和一致性哈希
![](img/92b6bf9ab0a831619ca9f08d88d90435.png)
这显示了在移至最佳匹配哈希函数之前和之后,每个清漆节点每秒请求之间的方差变化。
### 其他注意事项
### 节点增长
在任一模型中,节点增长将意味着键空间移位,从而导致缓存失效。 在一致的哈希模型中,预测将失效的键的百分比要容易得多。 基本上为 1 / N(N 是添加新节点之前的缓存节点数)。 使用静态分区模型,除非您对要从中获取键空间的节点的请求进行分析,否则最糟糕的情况是小于或等于键上键的总百分比。 您从中获取键空间的节点。
### 节点故障
使用静态分区时,除非您提供故障转移选项,否则单节点故障将导致无法访问 1 / N 密钥。 HAProxy 确实允许您拥有一个备用节点,但是现在您可以决定了。 每个密钥空间有 2N 个缓存节点(一个活动,一个备用)或共享的备用节点。 一种极端情况是 浪费 占硬件的 50%,其中频谱的另一端(所有活动节点之间共享 1 个备用节点)意味着两个故障节点导致备用 支持其他活动节点的密钥空间的 2 倍。
使用一致的哈希,将自动处理节点故障。 删除一个节点后,将移动 1 / N 个键(导致 1 / N 个键无效),并且每个剩余的活动节点的键空间均匀增加。
### 正在清除缓存
将清除请求发送到单个清漆节点很容易,但是从多个清漆节点清除也应该很容易。 不必使代理服务器和清除服务器保持同步,最简单的方法是通过同一代理服务器发送所有清除请求。
拒绝来自非本地 IP 空间的清除尝试非常重要,以防止任何恶意的批量清除。
### 获得的经验教训
* 您知道尚未回答的问题的答案。 面对扩展挑战时,请不要忽视您已经在其他地方使用的模式。
* 通过简单扩展。 在短期内可能会增加复杂性以克服可伸缩性挑战,但最终会赶上您。
* 了解您的哈希函数。 您使用的哈希函数与决定如何处理哈希值同样重要。
* 降级,不失败。 建议您的代理人监视自己达到后端的能力。 如果不能,则不要停止发布路由,而只是发布非优先级路由(例如,使用 OSPF 会增加路径成本)。 这样,如果所有后端都无法正常运行,您仍然可以提供错误页面,而不是无法访问。
### 谢谢
## * [Blake Matheny](http://tumblr.mobocracy.net/) 和 [Andrew Terng](http://andrew.tumblr.com/) 进行了散列函数比较并为 HAProxy 创建了补丁。
* [Bhaskar Maddala](http://maddalab.tumblr.com/) 与 HAProxy 社区合作,以获取 [此功能已添加到 HAProxy 1.5 版本](http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4.2-hash-type)
* [Arnoud Vermeer](http://blog.arnoudvermeer.nl/)[Aaron Prat](http://aaronprat.tumblr.com/) 与 ECMP / OSPF 流量分配有关。
## 相关文章 [
* [关于 HackerNews](https://news.ycombinator.com/item?id=8132473)
* [雅虎以 10 亿美元的价格收购了 Tumblr 架构](http://highscalability.com/blog/2013/5/20/the-tumblr-architecture-yahoo-bought-for-a-cool-billion-doll.html)
* [Tumblr Architecture-150 亿页面浏览量一个月,比 Twitter 难扩展](http://highscalability.com/blog/2012/2/13/tumblr-architecture-15-billion-page-views-a-month-and-harder.html)
对于任何混乱,我们深表歉意,共有 278 位 Tumblr 员工。
负责 Tumblr 所有外围(Perimeter-SRE)的团队由 6 人组成(包括一名经理)。
本文介绍了负责博客服务的外围部分的体系结构,这是我们流量更大的外围端点之一。
对于那些不了解哈希的人来说,它会使您变得 O(1)复杂,并且比对普通 b 树数据库的搜索要快。 令人惊讶的结果,我想这就是您扩展 tumblr 之类的方式的原因:)
非常有趣的文章。
但是有一个问题:您提到 BIRT 是 IP 平衡器,尽管 Haproxy 也是平衡器,但是对于 TCP / HTTP 级别,不是 IP。 那么负载均衡人员到底是谁呢?
感谢您分享这个幕后或“后台”视图。 “ 1.96 亿个博客”数量巨大,接近 1000 亿个帖子表明这些博客已被实际使用,而不是像其他平台那样,通常一旦注册就此后一直处于闲置状态。
从网络工程的角度来看,这非常有趣。 我猜想您的 HAProxy 框上正在运行 BIRD,然后将散列的流量平衡到 Varnish? 是否还可以通过 Varnish 服务器从您的边缘路由器提供网络图? 谢谢!
\ No newline at end of file
* 猜测用户对社交网络数据感兴趣的内容,并使用应用内的显式信号(+ /删除)完善这些猜测。
* 使用显式信号的问题很有趣,因为用户输入应该很快反映在其提要中。 如果用户连续从给定的发布者中删除了 5 篇文章,请立即停止向他们展示该发布者的文章,而不是明天。 这意味着没有时间在所有用户上运行另一个批处理作业。解决方案是在线学习:立即根据用户提供给我们的观察结果更新用户模型。
* 用户交互事件的原始流已保存。 这样可以在以后发生机器故障或类似情况时通过原始数据上的松散写回缓存丢失任何数据,从而在以后的原始事件中重新运行用户感兴趣的 ML。 在线学习中的漂移可以得到纠正,并且可以计算出更准确的模型。
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# 大,小,热还是冷-条带,Tapad,Etsy 和 Square 的健壮数据管道示例
# MongoDB 和 GridFS 用于内部和内部数据中心数据复制
> 原文: [http://highscalability.com/blog/2014/3/24/big-small-hot-or-cold-examples-of-robust-data-pipelines-from.html](http://highscalability.com/blog/2014/3/24/big-small-hot-or-cold-examples-of-robust-data-pipelines-from.html)
> 原文: [http://highscalability.com/blog/2013/1/14/mongodb-and-gridfs-for-inter-and-intra-datacenter-data-repli.html](http://highscalability.com/blog/2013/1/14/mongodb-and-gridfs-for-inter-and-intra-datacenter-data-repli.html)
[![](img/d95d6fc5fd7b47e48afbe6d9bd2b671b.png)](http://surf.transworld.net/1000104592/features/the-10-best-surf-photos-in-the-history-of-transworld-surf/)
![](img/8bf2ff01d2394d7e2b94688b0b76f3d8.png) *这是 LogicMonitor 副总裁 [Jeff Behl](jbehl@logicmonitor.com) 的来宾帖子。 [在过去 20 年中,Jeff](@jeffbehl) 有点过时,他为许多基于 SaaS 的公司设计和监督基础架构。*
*这是 [Hakka Labs](https://twitter.com/petesoder) 的创始人 [Pete Soderling](https://twitter.com/petesoder) 的[访客转发](http://www.hakkalabs.co/articles/big-small-hot-cold-data-needs-robust-pipeline),创建了软件工程师成长的社区。*
## 用于灾难恢复的数据复制
针对 MongoHQ 最近发表的题为“ [您没有大数据](http://blog.mongohq.com/you-dont-have-big-data/)”的帖子,我通常会同意作者的许多观点
灾难恢复计划的必然部分是确保客户数据存在于多个位置。 对于 LogicMonitor,这是一个基于 SaaS 的物理,虚拟和云环境的监视解决方案,我们希望在数据中心内外都可以复制客户数据文件。 前者用于防止设施中的单个服务器丢失,而后者用于在数据中心完全丢失的情况下进行恢复
但是,无论您称其为大数据,小数据,热数据还是冷数据-我们都有能力承认*更多*数据将保留下来-这是由于许多不同的因素造成的。
## 我们在哪里:Rsync
如本文所述,可能主要是由于存储成本随着时间的推移而降低。 其他因素包括对开放 API 的访问,在线上不断增长的消费者活动的数量,以及公司相互“共享”数据时在幕后形成的(主要是)幕后发展的大量其他激励措施。 (您知道[他们这样做](http://www.theguardian.com/business/2013/jun/24/barclays-bank-sell-customer-data),对吧?)
像大多数在 Linux 环境下工作的人一样,我们使用了可信赖的朋友 rsync 来复制数据。
但是,过去两年来我学到的最重要的事情之一是,对于具有远见卓识的公司而言,开始设计更强大的数据管道以收集,汇总和处理不断增长的数据量至关重要。 这样做的主要原因是能够以一致的方式准备好看似神奇的类似量子的操作的数据,这些操作可以推断数据之间的关系,否则这些关系肯定不会引起注意-在引用的文章中巧妙地描述为“ 从针头堆中确定针头的性质。”
![](img/5d8418f63b8ea168deb7b0bafc7c4dce.png)
但这提出了一个问题-精心设计的数据管道的特征是什么? 您难道不可以将所有数据都放入 Hadoop 并称之为一天吗?
Rsync is tried, true and tested, and works well when the number of servers, the amount of data, and the number of files is not horrendous.  When any of these are no longer the case, situations arise, and when the number of rsync jobs needed increases to more than a handful, one is inevitably faced with a number of issues:
正如许多工程师所发现的那样-答案是巨大的“不!” 我们汇总了 Stripe,Tapad,Etsy & Square 的智能工程师的四个示例,这些示例展示了您实际上可以在野外看到的一些实际数据管道的各个方面。
* 备份作业重叠
* 备份作业时间增加
* 过多的同时作业使服务器或网络超载
* 完成 rsync 作业后,没有简单的方法来协调所需的其他步骤
* 没有简便的方法来监视作业计数,作业统计信息并在发生故障时得到警报
## **Stripe 如何做到?**
Here at LogicMonitor [our philosophy](http://blog.logicmonitor.com/2012/07/17/our-philosophy-of-monitoring/) and reason for being is rooted in the belief that everything in your infrastructure needs to be monitored, so the inability to easily monitor the status of rsync jobs was particularly vexing (and no, we do not believe that emailing job status is monitoring!).  We needed to get better statistics and alerting, both in order to keep track of backup jobs, but also to be able to put some logic into the jobs themselves to prevent issues like too many running simultaneously.The obvious solution was to store this information into a database. A database repository for backup job metadata, where jobs themselves can report their status, and where other backup components can get information in order to coordinate tasks such as removing old jobs, was clearly needed.  It would also enable us to monitor backup job status via simple queries for information such as the number of jobs running (total, and on a per-server basis), the time since the last backup, the size of the backup jobs, etc., etc.   
我们在 [Stripe](http://www.hakkalabs.co/companies/stripe) 上与 Avi Bryant 进行了交谈,后者为我们很好地描述了 Stripe 进行数据管道构建的方式。
## MongoDB 作为备份作业元数据存储
> Stripe 从各种来源向 HDFS 馈送数据,其中许多是非结构化或半结构化的
> -例如服务器日志或 JSON
> 和 BSON 文档。 在每种情况下,第一步都是将
> 转换为结构化格式。 我们已经标准化了使用 Thrift 来定义
> 的逻辑结构,并使用 Parquet 作为磁盘上的存储
> 格式。
>
> 我们选择 Parquet 是因为它是 Cloudera Impala 查询引擎固有的高效列格式
> ,
> 使我们可以快速关联数据访问临时报告。
> Parquet 和 Thrift 的组合也可以有效地使用,并且
> 可以从 Twitter 的 Scalding 框架中惯用,这是我们为复杂批处理选择的
> 工具。
>
> 下一阶段是``非规范化'':为了保持我们的分析工作和
> 查询快速,我们会在 Scalding 中提前进行最常见的联接,
> 写入新的 Thrift 模式集。 同时,我们进行了大量的
> 增强和注释数据:例如,对 IP
> 地址进行地理编码,解析用户代理字符串或清除丢失的值。
>
> 在许多情况下,这会导致结构具有嵌套结构,
> 在 Scalding 中效果很好,并且哪个 Parquet 很高兴存储,但是
> 目前 Impala 无法查询。 我们开发了一个简单的工具
> ,该工具可将任意嵌套的 Parquet 数据转换为等效的
> 扁平化架构,并在必要时使用它来
> 维护每个数据源的并行副本以供 Impala 使用。
> 我们期待着 Impala 的未来版本,该版本可能会删除
> 这个额外的步骤。
The type of backup job statistics was more than likely going to evolve over time, so MongoDB came to light with its “[schemaless](http://blog.mongodb.org/post/119945109/why-schemaless)” document store design.  It seemed the perfect fit: easy to setup, easy to query, schemaless, and a simple JSON style structure for storing job information.  As an added bonus, MongoDB replication is excellent:  it is robust and extremely easy to  implement and maintain.  Compared to MySQL, adding members to a MongoDB replica set is auto-magic.So the first idea was to keep using rsync, but track the status of jobs in MongoDB. But it was a kludge to have to wrap all sorts of reporting and querying logic in scripts surrounding rsync.  The backup job metainfo and the actual backed up files were still separate and decoupled, with the metadata in MongoDB and the backed up files residing on a disk on some system (not necessarily the same).  How nice it would be if the the data and the database were combined.  If I could query for a specific backup job, then use the same query language again for an actual backed up file and get it.  If restoring data files was just a simple query away...  [Enter GridFS](http://docs.mongodb.org/manual/applications/gridfs/).
## **Tapad 的数据管道**
## 为什么选择 GridFS
[Tapad](http://www.hakkalabs.co/companies/tapad) 是纽约市的一家广告技术公司,在过去几年中,其流量和数据均实现了大幅增长。 因此,我联系了他们的 CTO [Dag Liodden](http://www.hakkalabs.co/engineers/dag-liodden) ,以了解他们如何构建数据管道以及他们使用的一些策略和工具。 用达格的话来说,这是他们的做法:
You can read up on the details GridFS on the MongoDB site, but suffice it to say it is a simple file system overlay on top of MongoDB (files are simply chunked up and stored in the same manner that all documents are).  Instead of having scripts surround rsync, our backup scripts store the data and the metadata at the same time and into the same place, so everything is easily queried.
* 所有摄取的数据都以 pub-sub 方式流过消息队列(我们使用 Kafka 并每小时通过它推送多个 TB 数据)
* 所有数据均使用支持架构演进的一致的非规范化架构进行编码(我们使用 Avro 和 Protocol Buffers)
* 我们的大多数数据存储都从消耗消息队列的流程进行实时更新(将热数据推送到 Aerospike 和 Cassandra,将实时可查询的数据推送到 Vertica,并且原始事件通常存储有来自 Aerospike 集群的数据, 在 HDFS 中)
* 高级分析和数据科学计算通常在 HDFS 中对非规范化数据执行
* 实时更新始终可以通过脱机批处理作业复制到 HDFS 存储的数据上。 我们努力使我们的计算逻辑,使其可以在流中*和*以批处理 MR 模式运行,而无需进行任何修改
当然,MongoDB 复制可与 GridFS 一起使用,这意味着备份的文件可立即在数据中心内和异地复制。 通过 Amazon EC2 内部的副本,可以拍摄快照以保留所需的尽可能多的历史备份。 现在,我们的设置如下所示:
他指出,最后一点使他们可以随意更改其流计算,然后用更新的预测回填其他数据存储。
![](img/3c3ccfd357f047d89266ff1df34f8b30.png)
Dag 还解释了在存储方面使用多种类型的数据技术背后的“原因”,并解释了它们中的每一个都有其自己的特定“最佳位置”,这使其对它们具有吸引力:
优点
* Kafka:高吞吐量并行发布订阅,但宽松的传递和延迟保证,有限的数据保留和无查询功能。
* Aerospike:按键(我们拥有 32 亿个键和 4TB 复制数据),跨数据中心复制,高可用性但查询功能非常有限,按键具有极快的随机访问读/写性能
* Cassandra:中等的随机访问读/写性能,原子计数器和数据模型,非常适合时间序列存储。 灵活的一致性模型和跨数据中心复制。
* HDFS:高吞吐量和廉价的存储。
* Vertica:快速和强大的即席查询功能,用于交互式分析,高可用性,但不支持嵌套的数据结构,多值属性。 基于存储的定价使我们限制了我们在此处放置的数据量。”
* 作业状态信息可通过简单查询获得
* 备份作业本身(包括文件)可以通过查询检索和删除
* 复制到异地位置实际上是立即的
* 分片可能
* 借助 EBS 卷,通过快照进行 MongoDB 备份(元数据和实际备份数据)既简单又无限
* 自动化状态监控很容易
## **Etsy 如何处理数据**
## 通过 LogicMonitor 进行监控
再举一个例子,我们联系了 [Etsy 的](http://www.hakkalabs.co/companies/etsy)数据团队的工程经理 Rafe Colburn,并询问他们如何处理他们的管道。 这是 Rafe 的独家新闻:
LogicMonitor 认为,从物理级别到应用程序级别的基础架构的所有方面都应位于同一监视系统中:UPS,机箱温度,OS 统计信息,数据库统计信息,负载平衡器,缓存层,JMX 统计信息,磁盘 写入延迟等)。所有都应该存在,其中包括备份。 为此,LogicMonitor 不仅可以监视 MongoDB 的常规统计信息和运行状况,还可以对 MongoDB 执行任意查询。 这些查询可以查询任何内容,从登录静态信息到页面视图,再到最后一个小时内完成的(猜测是什么?)备份作业。
> Etsy 的分析渠道不是特别线性。 它从我们的工具开始,它由一个事件记录器组成,该事件记录器在浏览器中运行,而另一个事件记录器可以从后端调用。 两者都 ping 一些内部“信标”服务器。
>
> 实际上,我们使用良好的旧 logrotate 程序将生成的 Apache 访问日志在达到一定大小时运送到 HDFS,并使用 Hadoop 处理它们。 我们还将每晚对生产数据(驻留在 MySQL 中)进行快照,并将其复制到 HDFS 中,以便我们可以将点击流数据添加到事务数据中。
>
> 通常,我们会将 Hadoop 作业的输出发送到 Vertica 数据仓库,在该仓库中我们也复制生产数据,以进行进一步分析。 我们使用这些数据来提供我们自己的报告和分析工具。
>
> 对于 [etsy.com](http://etsy.com/) 上使用从 Hadoop 作业生成的数据的功能,我们有一个自定义工具,该工具获取作业的输出并将其存储在分片的 MySQL 集群中,可以在该集群上进行大规模访问。 今年,我们正在考虑将 Kafka 集成到管道中,以将数据从我们的工具移至 Hadoop(以及流分析工具),并将数据从我们的分析平台发送回公共站点。
Now that our backups are all done via MongoDB, I  can keep track of (and more importantly, be alerted on):
## **Square 的方法**
* 每台服务器运行的备份作业数
* 所有服务器之间同时执行的备份数
* 任何未备份超过 6 个小时的客户门户
* MongoDB 复制滞后
拥有复杂数据管道的公司的另一个示例是 [Square](http://www.hakkalabs.co/companies/square) 。 我们与他们的工程经理之一 [Pascal-Louis Perez](http://www.hakkalabs.co/engineers/pascal-louis-perez) 取得了联系,他们为我们提供了他们的管道架构的战略视图。
### 复制滞后
由于支付在整个系统中的重要性,Square 已在整个数据管道中扩展了“对帐”的概念; 每个转换数据必须能够被审核和验证。 据 Pascal 称,这种方法的主要问题在于扩展规模可能具有挑战性。 对于收到的每笔付款,“大约需要 10 到 15 个会计分录,对帐系统的规模因此必须比处理的帐目规模大一个数量级,而处理的帐目已经非常大。”
![](img/5a3a770e6603b39a268e7856bbd86972.png)
Square 解决此问题的方法利用流处理,这使他们可以将相应的数据域映射到不同的流。 用 Pascal 的话来说,“流表示将数据流水线与数据源的多样性区分开的第一层抽象。下一层是将多个流之一组合在一起并产生一个或多个流的运算符。一个示例运算符是” “匹配器”,它接收两个流,从中提取相似种类的密钥,并根据匹配条件产生两个流。
### 工作完成
Pascal 指出,流处理和基于流的运算符的系统类似于关系代数及其运算符,但是在这种情况下,它是实时的并且具有无限关系。
![](img/501c0f8d17f23d06dd79c7855378d1ad.png)
很明显,将数据塞入 Hadoop 并不会为您提供这些功能!
有趣的例子特别时髦。 在前端,您会看到艺术家和手工艺人像在线公开市场一样出售其商品。 可以很好地了解后端的工作方式。
这是一个非常有用的技术概述,它对我来说是个新名词-数据管道如何工作。 我最近一直在使用 [TitanDB](http://thinkaurelius.github.io/titan/ "TitanDB") 和 hbase 来处理图形方面,您可以在此处阅读[,尽管它不是真实的示例。](http://tjadclark.com/blog/article/11-big-data-putting-it-in-a-graph "Big data in a graph")
看到在现实世界中有使用 HBase 的用例,这使我对将来使用 HBase 的决策更有信心。
\ No newline at end of file
您是否正在使用保险丝访问 GridFS,或者是否正在根据 API 编写所有代码?
\ No newline at end of file
此差异已折叠。
# 使用 AWS,Scala,Akka,Play,MongoDB 和 Elasticsearch 构建社交音乐服务
# 每天处理 1 亿个像素-少量竞争会导致大规模问题
> 原文: [http://highscalability.com/blog/2014/3/11/building-a-social-music-service-using-aws-scala-akka-play-mo.html](http://highscalability.com/blog/2014/3/11/building-a-social-music-service-using-aws-scala-akka-play-mo.html)
> 原文: [http://highscalability.com/blog/2013/1/21/processing-100-million-pixels-a-day-small-amounts-of-content.html](http://highscalability.com/blog/2013/1/21/processing-100-million-pixels-a-day-small-amounts-of-content.html)
![](img/7887820329b58171ca35d8132a92ae4c.png)
![](img/5088f2340fb872cea42ebbdd8c5dbfc1.png)
*这是[前 Roem Hermon](https://twitter.com/margolis20) , [serendip.me](http://serendip.me) 的首席架构师 [Rotem Hermon](https://twitter.com/margolis20) 的来宾转贴,涉及在进行启动音乐服务后的体系结构和扩展注意事项 。*
*这是 [Gordon Worley](http://www.linkedin.com/pub/gordon-worley/39/977/257) 的来宾帖子, [Korrelate](http://korrelate.com/) 的软件工程师在其中将在线购买与离线购买相关联(查看他们在这里做了什么)。*
[serendip.me](http://serendip.me) 是一项社交音乐服务,可以帮助人们发现朋友分享的美妙音乐,还可以将他们介绍给他们的“音乐灵魂伴侣”,即他们社交圈之外的人,他们在音乐方面有着相似的品味
几周前,我们一天早上来到办公室,发现所有服务器警报都响了。 像素日志处理落后了 8 个小时,并且没有取得进展。 查看日志后,我们发现有一个大客户在夜间上线,为我们提供的流量比最初告诉我们的要多 10 倍。 我不会说我们感到惊慌,但办公室肯定比平时更加​​紧张。 但是,在接下来的几个小时中,由于有远见和快速的思考,我们得以扩大规模以处理增加的负载并清除积压的日志,以使日志处理恢复到稳定状态
Serendip 在 AWS 上运行,并基于以下堆栈构建: [scala](http://www.scala-lang.org/) (和某些 Java), [akka](http://akka.io/) (用于处理并发性),[播放框架](http://www.playframework.com/)(用于 Web 和 API 前端), [MongoDB](http://www.mongodb.org/)[Elasticsearch](http://elasticsearch.org/)
在 Korrelate,我们部署了[跟踪像素](http://en.wikipedia.org/wiki/Web_bug)(也称为信标或网络错误),我们的合作伙伴将其用于向我们发送有关其用户的信息。 这些微小的 Web 对象不包含可见内容,但可以包含透明的 1 乘 1 gif 或 Javascript,并允许我们的合作伙伴在有人看到广告或采取与广告相关的操作时通知我们,而无需向我们发送广告服务器日志。 例如,当我们的一个合作伙伴展示广告时,他们通过将展示跟踪像素作为图像包含在 iframe 中或嵌入以我们的像素为源的脚本标签来触发我们的展示跟踪像素。 他们的广告会动态生成像素的网址,因此可以在查询字符串中向我们传递有关所展示广告的信息。 对于选择接受第三方 cookie 的用户,我们还可以在用户上设置和读取 Korrelate 用户 ID cookie,以便我们可以跟踪他们的活动,并在[聚合和匿名化](http://korrelate.com/privacy/)之后使用它,以提供我们的 分析产品
### 选择堆栈
在早期,甚至在 Korrelate 成为 Korrelate 之前,我们就知道有一天我们需要每天摄取数十亿个跟踪像素。 因此,当我们开始编写像素对数处理器时,我们进行了架构选择,使其可以扩展。
建立 serendip 的挑战之一是从第一天起就需要处理大量数据,因为 serendip 的主要特征是它收集**并从公共音乐服务在 Twitter** 上共享的每一首音乐。 因此,当我们讨论选择要使用的语言和技术的问题时,一个重要的考虑因素就是扩展能力
最初,日志处理器是用 Java servlet 编写的,但是事实证明这很难在服务器上进行管理,而且我们都不满意使用 Java 进行编程。 寻找替代方案,因为当时我们使用 [Pentaho](http://www.pentaho.com/) 分析工具套件来生成有关原始数据的报告,所以我们转向了[水壶](http://kettle.pentaho.com/)(俗称 Pentaho 数据集成) 数据
JVM 似乎是我们系统经过验证的性能和工具的正确基础。 它也是许多开源系统(例如 Elasticsearch)的选择语言,这使**使用其本机客户端**-很大的优势
Kettle 是在 JVM 上运行的提取转换加载工具,可以充分利用多线程来快速处理大量数据。 它还具有一个称为 Spoon 的易于使用的 GUI 工具,用于设计 Kettle 程序,该程序需要大量的配置,而编程却相对较少。 我们非常享受使用 Kettle 创建和部署日志处理的速度。 随着时间的流逝,我们意识到了水壶的局限性
当我们研究 JVM 生态系统时,scala 脱颖而出,成为一种有趣的语言选择,它允许现代方法编写代码,同时保持与 Java 的完全互操作性。 支持 scala 的另一个论点是 **akka actor 框架,它似乎非常适合流处理基础结构**(确实如此!)。 Play 网络框架才刚刚开始被采用,并且看起来很有希望。 早在 2011 年初我们刚开始时,这些仍然是最前沿的技术。 因此,我们当然非常高兴,到 2011 年底,scala 和 akka 合并成为 [Typesafe](http://typesafe.com/) ,随后不久 Play 就加入了
通过 Kettle 作业运行大量数据需要大量内存(在我写这篇文章时,日志处理器需要 8 GB 内存来处理 250,000 条记录的文件)。 在开发方面,使用 Spoon 易用性的缺点是源文件仅是人类可编辑的 XML,因此我们无法利用 Git 正常工作流来轻松合并并发开发分支,从而迫使我们 就像有人处理日志处理器时源被锁定一样。 但是尽管有这些限制,我们仍继续使用 Kettle,因为它正在工作,我们还有很多其他工作要做,并且我们知道我们可以在需要时扩大规模,即使它会很昂贵
**选择 MongoDB 是因为它结合了开发人员的友好性,易用性**,功能集和可能的可伸缩性(使用自动分片)。 我们很快了解到,要使用和查询数据的方式将需要在 MongoDB 上创建很多大索引,这将使我们很快遇到性能和内存问题。 因此,我们一直主要将 MongoDB 用作键值文档存储,还依赖于其原子增量来获取需要计数器的多个功能。
通过这种使用,MongoDB 变得非常可靠。 它也很容易操作,但是主要是因为我们设法*避免使用分片*并使用单个副本集(MongoDB 的分片架构非常复杂)。
几个月前,我们不得不开始同时运行两个日志处理器,以适应我们的负载。 这是一个很好的体验,因为它有助于揭示日志处理中的问题区域。
为了查询我们的数据,我们需要一个具有完整搜索功能的系统。 在可能的开源搜索解决方案中, **Elasticsearch 成为最具扩展性和面向云的系统**。 它的动态索引架构以及它提供的许多搜索和构面功能使我们可以在其之上构建许多功能,从而使其成为我们体系结构的核心组成部分
当只有一个日志处理器运行时,我们遇到的唯一性能问题与过程的各个部分有关,需要很长时间才能完成。 例如,我们发现对数据库中表的更新花费了很长时间,因此我们几乎将所有存储像素数据的表都转换为仅追加,以便快速插入。 某些表不能仅作追加操作,因此要与我们创建的加载表一起使用,日志处理将快速将数据插入到表中,然后稍后再回过头来将加载表与数据库中的主表进行同步 比我们执行 upsert 的速度快
我们选择**自己管理 MongoDB 和 Elasticsearch** ,并且出于两个主要原因,不使用托管解决方案。 首先,我们希望完全控制两个系统。 我们不想依靠其他因素进行软件升级/降级。 其次,我们处理的数据量意味着托管解决方案比直接在 EC2 上直接管理它要昂贵
调出第二个日志处理器会使我们面临新的问题。 尽管由于对仅追加表的非阻塞写入而使我们能够快速写入数据库,但是需要与加载表同步的少数几个表引起了足够的争用,两个日志处理器在运行一个日志处理器时几乎没有任何收益。 为了解决这个问题,我们将日志处理分为两部分:仅写到仅追加表的部分和需要插入堆表的部分。 这样,我们就可以打开仅追加日志处理器的两个实例(仅是堆表日志处理器之一),并获得良好的吞吐量,因为堆表从每个需要插入或更新的日志文件接收的数据相对较少,而追加- 只有表从每个日志文件接收很多数据
### 一些数字
因此,在像素大量涌入的早晨,我们认为我们已经做好了扩大规模的准备。 我们在几个小时之内启动了运行其他附加仅日志处理器实例的其他服务器,并开始处理日志(堆表日志处理器自行继续足够快地运行以保持运行状态)。 但是,我们很快发现,日志处理器中仍然存在争用。
Serendip 的“泵”(处理 Twitter 公众流和 Facebook 用户供稿的部分)**每天大约消化 5,000,000 个项目**。 这些项目通过一系列“过滤器”传递,这些过滤器检测并解析受支持服务(YouTube,Soundcloud,Bandcamp 等)的音乐链接,并在它们之上添加元数据。 泵和过滤器作为 akka actor 运行,并且整个过程由单个 **m1.large EC2 实例**管理。 如果需要,可以通过使用 akka 的远程角色将系统分发到处理器集群来轻松扩展
为了跟踪日志处理的方式,我们将一些基本统计信息写到了几个审计表中,这些统计信息涉及日志处理需要多长时间以及处理多少像素。 为了收集这些数据,我们使用了 Kettle 的内置日志记录功能将信息写入表格,然后将其合并为对我们有用的摘要形式。 事实证明,Kettle 的编写方式要求在审计表上请求排他表级锁以将其写入。 而且由于在日志处理器实例的每次运行中都会发生数十次,因此对于相同的表,我们有数百个请求彼此等待。 每个请求的清除速度都很快,但是加了一点点延迟,导致日志处理器实例在应在 2 中完成时需要花费 15 分钟的时间来运行
在这些项目中,我们每天大约可获得 850,000 个有效项目(即真正包含相关音乐链接的项目)。 这些项目在 Elasticsearch 中(以及在 MongoDB 中用于备份和保持计数器)都已建立索引。 由于每个有效项都意味着更新多个对象,因此在 Elasticsearch 中我们获得的**索引速率为〜40 / sec**
我们**在 Elasticsearch 中保留项目(推文和帖子)的每月索引**。 每个月度索引包含**〜2500 万个项目,并具有 3 个碎片**。 群集以 **4 个节点运行,每个节点在 m2.2xlarge 实例**上。 此设置有足够的内存来运行我们需要的数据搜索。
我们关闭了 Kettle 的内置日志记录功能,将其替换为我们自己的一些不需要表级锁定的代码,并且日志处理器之间的数据库争用消失了。 我们以艰难的方式学到了我们经常听到的智慧,但显然还没有被内在化:**少量争用可能成为大规模的问题**
我们的 MongoDB 集群处理更多数据类型,计数器和统计信息更新时,每秒**为 100 个写入/秒,每秒 300 次为**读取。 副本集具有在 **m2.2xlarge 实例上运行的主节点,在 m1.xlarge 实例**上运行的辅助节点
通过从日志处理中完全消除争用,我们能够快速启动十多个日志处理器实例,并使用它们来快速处理积压的事务,然后将其调节回稳定状态。 在短短 24 小时内,一切恢复正常,节省了一些额外的硬件和日志处理器
### 建立一个提要
尽管日志处理器现在可以处理高级别的并发性,但仍需要对其进行重建以处理更多的像素,而无需当前日志处理器的高昂成本。 调出当前日志处理器的新实例意味着添加具有大量 RAM 的服务器(通常大约需要 24 GB,以便我们在每台服务器上运行两个日志处理器,以及用于其他进程的额外 RAM),这是很昂贵的。 而且,当前的日志处理器在与数据库的有限连接上仍然面临潜在的争用。 为了解决这个问题,我们需要寻找减少需要向数据库传递数据的进程数量的方法。
当我们开始设计 Serendip 的主要音乐供稿的体系结构时,我们知道我们希望供稿是动态的并对用户的动作和输入做出反应。 如果用户给某首歌“加油”或“播放”特定艺术家,我们希望该动作立即反映在提要中。 如果用户“不喜欢”艺术家,则我们不应再次播放该音乐。
我们还希望提要是来自多个来源的音乐的组合,例如朋友共享的音乐,喜爱的艺术家的音乐以及具有相同音乐品味的“建议”用户共享的音乐。
这些要求意味着采用“ [扇出即写](http://www.quora.com/What-is-the-best-storage-solution-for-building-a-news-feed-MongoDB-or-MySQL)”的方法来创建提要是不可行的。 我们需要一个选项,以使用与用户有关的所有信号实时构建提要。 Elasticsearch 提供的功能集使我们能够构建这种实时提要生成。
提要算法包含几种“策略”,用于选择要在每次提要中以不同比率动态组合的项目。 每种策略都可以考虑到最新的用户操作和信号。 将策略的组合转换为对实时数据的几次搜索,这些搜索由 Elasticsearch 不断索引。 由于数据是基于时间的,并且索引是每月创建的,因此**我们始终只需要查询完整数据**的一小部分。
幸运的是,Elasticsearch 可以很好地处理这些搜索。 它还提供了扩展此体系结构的已知途径-**写入可以通过增加分片**的数量进行缩放。 可以通过添加更多副本和物理节点来扩展搜索范围。
查找“音乐灵魂伴侣”(通过音乐品味匹配用户)的过程很好地利用了 Elasticsearch 的**构面(聚合)功能。 作为持续的社交流处理的一部分,该系统通过计算遇到的社交网络用户的顶级共享艺术家(使用对共享音乐的多面搜索)来准备数据。**
当偶然的用户发出信号(通过播放音乐或与提要互动)时,它可以触发对该用户的音乐灵魂伴侣的重新计算。 该算法会根据喜欢的艺术家列表(不断更新)找到最匹配的其他用户,并权衡受欢迎程度,分享数量等其他参数。然后应用另一组算法来过滤垃圾邮件发送者(是的, 是音乐垃圾邮件发送者……)和离群值。
我们发现,此过程可为我们提供足够好的结果,同时又使我们免于需要其他可以运行更复杂的群集或推荐算法的系统。
### 监控和部署
Serendip 正在使用 [ServerDensity](http://www.serverdensity.com/) 进行监视和警报。 这是一款易于使用的托管解决方案,具有不错的功能集和合理的启动价格。 ServerDensity 本机提供服务器和 MongoDB 监视。 我们还大量使用了向其中报告自定义指标的功能,以报告内部系统统计信息。
内部统计信息收集机制为系统中发生的每个操作收集事件,并将其保存在 MongoDB 收集中。 定时作业每分钟一次从 MongoDB 中读取这些统计信息,并将其报告给 ServerDensity。 这使我们可以使用 ServerDensity 监视和警告 Elasticsearch 以及我们的运营数据。
使用 Amazon Elastic Beanstalk 完成服务器和部署的管理。 Elastic Beanstalk 是 AWS 的受限 PaaS 解决方案。 它非常容易上手,尽管它并不是真正功能齐全的 PaaS,但其基本功能足以满足大多数常见用例的需要。 它提供了简单的自动缩放配置,还可以通过 EC2 进行完全访问。
使用驻留在 EC2 上的 [Jenkins](http://jenkins-ci.org/) 实例完成应用程序的构建。 Play Web 应用程序打包为 WAR。 [构建后脚本](https://github.com/rore/beanstalk-upload)将 WAR 作为新的应用程序版本推送到 Elastic Beanstalk。 新版本不会自动部署到服务器,而是手动完成的。 通常将其首先部署到登台环境中进行测试,然后将其批准部署到生产环境中。
### 外卖
总结一下,这是从构建 serendip 中学到的一些重要经验教训,而不是通过任何特殊命令得出的。
1. **知道如何缩放**。 您可能不需要从第一天开始进行扩展,但是您需要知道系统的每个部分如何扩展以及扩展到什么程度。 如果扩展需要时间,请提前给自己足够的时间。
2. **准备峰**。 特别是在初创企业的生命中,如果您始终以接近最高的容量运行,那么一个救生员或 reddit 帖子就会使您的系统瘫痪。 保持足够的余量,以便您可以处理突然的负载或准备好快速扩展。
3. **选择一种不会阻碍您的语言**。 确保要使用的技术使用您的语言的本地客户端,或者至少具有主动维护的客户端。 不要卡在等待库更新。
4. **相信炒作**。 您需要一种将随您的产品一起增长并且不会过早死亡的技术。 一个充满活力,活跃的社区以及对该技术的一些质疑可以很好地表明其生存。
5. **不要相信炒作**。 查找有关您正在评估的技术的简报。 他们可以教您有关它的弱点。 但也不要太当真,当事情无法按预期进行时,人们往往会情绪激动。
6. **玩得开心**。 选择一种使您兴奋的技术。 一个让您认为“哦,太酷了,我该怎么办”。 毕竟,这也是我们的目标。
\ No newline at end of file
我们还希望从 Kettle 转移到一个使代码管理更容易的系统。 为此,我们已开始使用 [Storm](http://storm-project.net/) 构建新的日志处理器,该处理器提供了用于创建自定义实时流处理工作流的灵活框架,类似于 [Hadoop](http://hadoop.apache.org/) 提供了灵活框架的方式 用于批处理。 尽管仅 Storm 本身提供的内置功能要比 Kettle 少得多,但也不必这样做,因为 Storm 工作流可以用任何语言编写,也可以使用我们想要的任何现有库。 由于我们的大多数代码已经在 Ruby 中,因此我们能够利用现有的代码库在 Ruby 中构建 Storm 工作流。 基于其他使用 Storm 的[其他人](https://github.com/nathanmarz/storm/wiki/Powered-By),我们希望看到我们的 Storm 日志处理器每天可以扩展到数十亿像素。
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册