解密IFTTT的數(shù)據(jù)架構(gòu)
什么是IFTTT?
IFTTT是“if this then that”的縮寫(xiě),如果這樣就那樣。this 稱(chēng)為 trigger,而 that 稱(chēng)為 action。每條 if this then that 稱(chēng)為 task。IFTTT可以實(shí)現(xiàn)多種互聯(lián)網(wǎng)應(yīng)用的協(xié)同工作。
為了實(shí)現(xiàn) IFTTT的功能,IFTTT必須獲得授權(quán)。
走近IFTTT
隨著信息技術(shù)的發(fā)展,人們?cè)谌粘I詈凸ぷ髦卸疾豢杀苊獾囊玫洁]箱、聊天工具、云存儲(chǔ)等網(wǎng)絡(luò)服務(wù)。然而,這些服務(wù)很多時(shí)候都是單獨(dú)運(yùn)行的,不能很好的實(shí)現(xiàn)資源共享。針對(duì)該問(wèn)題,IFTTT提出了“讓互聯(lián)網(wǎng)為你服務(wù)”的概念,利用各網(wǎng)站和應(yīng)用的開(kāi)放API,實(shí)現(xiàn)了不同服務(wù)間的信息關(guān)聯(lián)。
例如,IFTTT可以把指定號(hào)碼發(fā)送的短信自動(dòng)轉(zhuǎn)發(fā)郵箱等。為了實(shí)現(xiàn)這些功能,IFTTT搭建了高性能的數(shù)據(jù)架構(gòu)。近期,IFTTT的工程師Anuj Goyal對(duì)數(shù)據(jù)架構(gòu)的概況進(jìn)行了介紹,并分享了在操作數(shù)據(jù)時(shí)的一些經(jīng)驗(yàn)和教訓(xùn)。
在IFTTT,數(shù)據(jù)非常重要——業(yè)務(wù)研發(fā)和營(yíng)銷(xiāo)團(tuán)隊(duì)依賴(lài)數(shù)據(jù)進(jìn)行關(guān)鍵性業(yè)務(wù)決策;產(chǎn)品團(tuán)隊(duì)依賴(lài)數(shù)據(jù)運(yùn)行測(cè)試/了解產(chǎn)品的使用情況,從而進(jìn)行產(chǎn)品決策;數(shù)據(jù)團(tuán)隊(duì)本身也依賴(lài)數(shù)據(jù)來(lái)構(gòu)建類(lèi)似Recipe推薦系統(tǒng)和探測(cè)垃圾郵件的工具等;甚至合作伙伴也需要依賴(lài)數(shù)據(jù)來(lái)實(shí)時(shí)了解Channel的性能。鑒于數(shù)據(jù)如此重要,而IFTTT的服務(wù)每天又會(huì)產(chǎn)生超過(guò)數(shù)十億個(gè)事件,IFTTT的數(shù)據(jù)框架具備了高度可擴(kuò)展性、穩(wěn)定性和靈活性等特點(diǎn)。接下來(lái),本文就對(duì)數(shù)據(jù)架構(gòu)進(jìn)行詳細(xì)分析。
1.數(shù)據(jù)源
在IFTTT,共有三種數(shù)據(jù)源對(duì)于理解用戶(hù)行為和Channel性能非常重要。首先,AWS RDS中的MySQL集群負(fù)責(zé)維護(hù)用戶(hù)、Channel、Recipe及其相互之間的關(guān)系等核心應(yīng)用。運(yùn)行在其Rails應(yīng)用中的IFTTT.com和移動(dòng)應(yīng)用所產(chǎn)生的數(shù)據(jù)就通過(guò)AWS Data Pipeline,導(dǎo)出到S3和Redshift中。其次,用戶(hù)和IFTTT產(chǎn)品交互時(shí),通過(guò)Rails應(yīng)用所產(chǎn)生的時(shí)間數(shù)據(jù)流入到Kafka集群中。***,為了幫助監(jiān)控上百個(gè)合作API的行為,IFTTT收集在運(yùn)行Recipe時(shí)所產(chǎn)生的API請(qǐng)求的信息。這些包括反應(yīng)時(shí)間和HTTP狀態(tài)代碼的信息同樣流入到了Kafka集群中。
2.IFTTT的Kafka
IFTTT利用Kafka作為數(shù)據(jù)傳輸層來(lái)取得數(shù)據(jù)產(chǎn)生者和消費(fèi)者之間的松耦合。數(shù)據(jù)產(chǎn)生者首先把數(shù)據(jù)發(fā)送給Kafka。然后,數(shù)據(jù)消費(fèi)者再?gòu)腒afka讀取數(shù)據(jù)。因此,數(shù)據(jù)架構(gòu)可以很方便的添加新的數(shù)據(jù)消費(fèi)者。
由于Kafka扮演著基于日志的事件流的角色,數(shù)據(jù)消費(fèi)者在事件流中保留著自己位置的軌跡。這使得消費(fèi)者可以以實(shí)時(shí)和批處理的方式來(lái)操作數(shù)據(jù)。例如,批處理的消費(fèi)者可以利用Secor將每個(gè)小時(shí)的數(shù)據(jù)拷貝發(fā)送到S3中;而實(shí)時(shí)消費(fèi)者則利用即將開(kāi)源的庫(kù)將數(shù)據(jù)發(fā)送到Elasticsearch集群中。而且,在出現(xiàn)錯(cuò)誤時(shí),消費(fèi)者還可以對(duì)數(shù)據(jù)進(jìn)行重新處理。
3.商務(wù)智能
S3中的數(shù)據(jù)經(jīng)過(guò)ETL平臺(tái)Cranium的轉(zhuǎn)換和歸一化后,輸出到AWS Redshift中。Cranium允許利用SQL和Ruby編寫(xiě)ETL任務(wù)、定義這些任務(wù)之間的依賴(lài)性以及調(diào)度這些任務(wù)的執(zhí)行。Cranium支持利用Ruby和D3進(jìn)行的即席報(bào)告。但是,絕大部分的可視化工作還是發(fā)生在Chartio中。

而且,Chartio對(duì)于只了解很少SQL的用戶(hù)也非常友好。在這些工具的幫助下,從工程人員到業(yè)務(wù)研發(fā)人員和社區(qū)人員都可以對(duì)數(shù)據(jù)進(jìn)行挖掘。
4.機(jī)器學(xué)習(xí)
IFTTT的研發(fā)團(tuán)隊(duì)利用了很多機(jī)器學(xué)習(xí)技術(shù)來(lái)保證用戶(hù)體驗(yàn)。對(duì)于Recipe推薦和問(wèn)題探測(cè),IFTTT使用了運(yùn)行在EC2上的Apache Spark,并將S3當(dāng)作其數(shù)據(jù)存儲(chǔ)。
5.實(shí)時(shí)監(jiān)控和提醒
API事件存儲(chǔ)在Elasticsearch中,用于監(jiān)控和提醒。IFTTT使用Kibana來(lái)實(shí)時(shí)顯示工作進(jìn)程和合作API的性能。在API出現(xiàn)問(wèn)題時(shí),IFTTT的合作者可以訪問(wèn)專(zhuān)門(mén)的Developer Channel,創(chuàng)建Recipe,從而提醒實(shí)際行動(dòng)(SMS、Email和Slack等)的進(jìn)行。

在開(kāi)發(fā)者視圖內(nèi),合作者可以在Elasticsearch的幫助的幫助下訪問(wèn)Channel健康相關(guān)的實(shí)時(shí)日志和可視化圖表。開(kāi)發(fā)者也可以通過(guò)這些有力的分析來(lái)了解Channel的使用情況。

6.經(jīng)驗(yàn)與教訓(xùn)
***,Anuj表示,IFTTT從數(shù)據(jù)架構(gòu)中得到的教訓(xùn)主要包括以下幾點(diǎn):
- 為了完全信任數(shù)據(jù),在處理流中加入若干自動(dòng)化的數(shù)據(jù)驗(yàn)證步驟非常重要!例如,IFTTT開(kāi)發(fā)了一個(gè)服務(wù)來(lái)比較產(chǎn)品表和Redshift表中的行數(shù),并在出現(xiàn)異常情況時(shí)發(fā)出提醒。
- 在類(lèi)似的復(fù)雜架構(gòu)中,設(shè)置合適的警告來(lái)保證系統(tǒng)工作正常是非常關(guān)鍵的!IFTTT使用Sematext來(lái)監(jiān)控Kafka集群和消費(fèi)者,并分別使用Pingdom和Pagerduty進(jìn)行監(jiān)控和提醒。
- 從一開(kāi)始就要使用集群,方便以后的擴(kuò)展!但是,在因?yàn)樾阅軉?wèn)題投入更多節(jié)點(diǎn)之前,一定要先認(rèn)定系統(tǒng)的性能瓶頸。例如,在Elasticsearch中,如果碎片太多,添加更多的節(jié)點(diǎn)或許并 不會(huì)加速查詢(xún)。***先減少碎片大小來(lái)觀察性能是否改善。
- 通過(guò)Kafka這樣的數(shù)據(jù)傳輸層實(shí)現(xiàn)的生產(chǎn)者和消費(fèi)者的隔離非常有用,且使得Data Pipeline的適應(yīng)性更強(qiáng)。例如,一些比較慢的消費(fèi)者也不會(huì)影響其他消費(fèi)者或者生產(chǎn)者的性能。
- 在長(zhǎng)期存儲(chǔ)中使用基于日期的文件夾結(jié)構(gòu)(YYYY/MM/DD)來(lái)存儲(chǔ)事件數(shù)據(jù)。這樣存儲(chǔ)的事件數(shù)據(jù)可以很方便的進(jìn)行處理。例如,如果想讀取某一天的數(shù)據(jù),只需要從一個(gè)文件夾中獲取數(shù) 據(jù)即可。
- 在Elasticsearch中創(chuàng)建基于時(shí)間(例如,以小時(shí)為單位)的索引。這樣,如果試圖在Elasticsearch中尋找過(guò)去一小時(shí)中的所有API錯(cuò)誤,只需要根據(jù)單個(gè)索引進(jìn)行查詢(xún)即可。
- 不要把單個(gè)數(shù)據(jù)馬上發(fā)送到Elasticsearch中,***成批進(jìn)行處理。這樣可以提高IO的效率。
- 根據(jù)數(shù)據(jù)和查詢(xún)的類(lèi)型,優(yōu)化節(jié)點(diǎn)數(shù)、碎片數(shù)以及每個(gè)碎片和重復(fù)因子的***尺寸都非常重要。