久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

高頻數(shù)據(jù)采集請求如何不影響主業(yè)務(wù)(7)

 印度阿三17 2021-03-11

上一篇文章討論了寫緩存的架構(gòu)解決方案,它雖然可以減少數(shù)據(jù)庫寫操作的壓力,,但也存在不足,。比如需要長期高頻插入數(shù)據(jù)時,這個解決方案就無法滿足,,本篇文章我們就圍繞這個問題逐步提出解決方案,。在架構(gòu)方案層層展開的過程中,你會發(fā)現(xiàn)不斷會有新問題需要考慮,。

一,、業(yè)務(wù)背景

因業(yè)務(wù)快速發(fā)展,公司系統(tǒng)日活用戶高達(dá)500萬,,基于現(xiàn)有業(yè)務(wù)模式,,業(yè)務(wù)側(cè)要求我們根據(jù)用戶行為做埋點(diǎn),旨在記錄用戶在指定頁面的所有行為,、開展數(shù)據(jù)分析與第三方進(jìn)行費(fèi)用結(jié)算,。(至于為啥要做結(jié)算,我就不說了,,嘿嘿)

當(dāng)然,,在埋點(diǎn)過程中,業(yè)務(wù)側(cè)還要求能在后臺實(shí)時查詢用戶行為和統(tǒng)計(jì)報(bào)表,。(這里雖然說是實(shí)時,,其實(shí)特定時間內(nèi)的延遲業(yè)務(wù)方還是能接受的,為確保描述的準(zhǔn)確性,,我們把它稱之為“準(zhǔn)實(shí)時”吧

為了能夠清晰的理解后續(xù)方案的建設(shè)思路,,我來簡單列舉點(diǎn)兒數(shù)據(jù)結(jié)構(gòu),免得后面出現(xiàn)理解偏差,。首先,,我們需要收集的原始數(shù)據(jù)結(jié)構(gòu)如下表所示:

指標(biāo) 備注
IMEI 用戶設(shè)備的IMEI
定位點(diǎn) 經(jīng)緯度
用戶ID
目標(biāo)ID 每個頁面、按鈕,、banner都有唯一識別id
目標(biāo)類型 頁面,、按鈕、banner等
事件動作 點(diǎn)擊,、進(jìn)入,、跳出等
From Url 來源URL
Current Url 當(dāng)前URL
To URL 去向URL
動作時間 觸發(fā)這個動作的時間
進(jìn)入時間 進(jìn)入該頁面的時間
跳出時間 跳出該頁面的時間
... ...

通過以上的數(shù)據(jù)結(jié)構(gòu),在后臺查詢原始數(shù)據(jù)時,,業(yè)務(wù)側(cè)不僅可以以城市(根據(jù)經(jīng)緯度換算),、性別(從業(yè)務(wù)表中查詢),、年齡、目標(biāo)類型,、目標(biāo)ID,、事件動作等作為查詢條件實(shí)時查看用戶行為數(shù)據(jù),還可以以時間,、性別,、年齡等維度實(shí)時查看每個目標(biāo)ID的總點(diǎn)擊數(shù)、平均點(diǎn)擊數(shù),、頁面轉(zhuǎn)換率等統(tǒng)計(jì)報(bào)表數(shù)據(jù),。

二、技術(shù)選型思路

根據(jù)以上業(yè)務(wù)場景,,我們提煉出了6點(diǎn)業(yè)務(wù)需求,,并針對業(yè)務(wù)需求梳理了技術(shù)選型相關(guān)思路。

1,、原始數(shù)據(jù)海量:對于這點(diǎn),,我們初步考慮HBase進(jìn)行持久化。

2,、對于埋點(diǎn)記錄的請求要快:埋點(diǎn)記錄服務(wù)會把原始埋點(diǎn)記錄存放在一個緩沖的地方,,以此來保證響應(yīng)速度。關(guān)于這點(diǎn)有好幾個緩存方案,,下面會展開討論,。

3、可通過后臺查詢原始數(shù)據(jù):如果使用HBASE直接作為查詢引擎,,查詢速度太慢了,,所以我們還需要使用ES來保存查詢頁面上作為查詢條件的字段和活動ID。

4,、各種統(tǒng)計(jì)報(bào)表的需求:關(guān)于數(shù)據(jù)可視化工具也有很多選擇,,比如kibana、grafana等,,考慮使用過程的靈活性,,我們最終選擇自己設(shè)計(jì)功能。

5,、能根據(jù)埋點(diǎn)日志生成費(fèi)用結(jié)算數(shù)據(jù):我們將費(fèi)用結(jié)算數(shù)據(jù)保存在MySQL中,。

6、需要一個框架將緩存中的數(shù)據(jù)進(jìn)行處理,,并保存到ES,、HBase和MySQL中:因?yàn)闃I(yè)務(wù)有準(zhǔn)實(shí)時查詢的需求,所以我們需要使用實(shí)時處理工具,。目前,,市面上流行的實(shí)時處理工具主要分為Storm、spark Steaming,、Apache Flink這三種,,一會兒我們也會展開說明。

為了更快理解這部分內(nèi)容,,畫了個簡單的架構(gòu)圖來說明,,如下圖所示:

高頻數(shù)據(jù)采集請求如何不影響主業(yè)務(wù)(7)

仔細(xì)觀察這張架構(gòu)圖,你會發(fā)現(xiàn)圖上還有兩個地方打了問好,,這是為什么呢,?這就涉及到我們接下來需要討論的4個問題。

1,、使用什么技術(shù)保存埋點(diǎn)數(shù)據(jù)的第一現(xiàn)場,?

市面上關(guān)于快速保存埋點(diǎn)數(shù)據(jù)的技術(shù)主要分為Redis、kafka,、本地日志這三種,,在上面的業(yè)務(wù)場景中,我們最終選擇了本地日志,。

說到這,,你可能想問:Redis跟Kafka到底哪里不好,為什么不使用呢,?我們先來說說Redis的AOF機(jī)制,,這點(diǎn)在前面第六篇文章也說過。

Redis的AOF機(jī)制會持久化保存Redis所有操作記錄,,用于服務(wù)器宕機(jī)后數(shù)據(jù)還原,。那么Redis什么時候?qū)OF落盤呢?

在Redis中存在一個AOF配置:appendfsync,,如果appendfsync配置成everysec,,AOF每秒落盤一次,不過這種配置方式有可能會丟失1秒的數(shù)據(jù),。如果appendfsync配置成always,,每次操作請求的記錄都落盤后再返回成功信息給客戶端,不過這種配置方式系統(tǒng)性能就會很慢,。因?yàn)閷τ诼顸c(diǎn)記錄的請求要求響應(yīng)快,,所以我們沒有選擇Redis。

接下來我們討論下kafka的技術(shù)方案,。

kafka的冗余設(shè)計(jì)是每個分區(qū)都有多個副本,,其中一個副本是Leader,其他副本都是Follower,,Leader主要負(fù)責(zé)處理所有的讀寫請求,,并同步給其他Follwer,。

那么kafka什么時候?qū)?shù)據(jù)從Leader同步給Follower呢?kafka的producer configs中也有個acks配置,,它的配置方式分為三種,。

  • acks=0:不等Leader將數(shù)據(jù)落到日志,kafka直接返回完成信號給客戶端,。這種方式雖然響應(yīng)很快,,但數(shù)據(jù)持久化沒有保障,數(shù)據(jù)如果沒有落到本地日志,,系統(tǒng)就會出現(xiàn)宕機(jī),,導(dǎo)致數(shù)據(jù)丟失。
  • acks=1:等Leader將數(shù)據(jù)落到本地日志,,但是不等Follower同步數(shù)據(jù),,kafka就直接返回完成信號給客戶端。
  • acks=all:等Leader將數(shù)據(jù)落到日志,,且等min.insync.replicas個Follower都同步數(shù)據(jù)后,,kafka再返回完成信號給客戶端。這種配置方式雖然數(shù)據(jù)有保證,,但響應(yīng)慢,。

通過以上的解釋,是否發(fā)現(xiàn)了使用Redis與kafka都會出現(xiàn)問題呢,?

如果我們想保證數(shù)據(jù)的可靠性,,必然需要犧牲系統(tǒng)性能,那么有沒有一個方案可以性能 可靠性同時兼得呢,?有的,,所以我們最終決定把埋點(diǎn)數(shù)據(jù)保存到本地日志中。

2,、使用什么技術(shù)(ES,、HBase、Mysql)把緩沖數(shù)據(jù)搬到持久化層呢,?

關(guān)于這個問題,,最簡單的方式是通過Logstash直接把日志文件中的數(shù)據(jù)搬運(yùn)到ES,但是問題來了,,業(yè)務(wù)側(cè)要求存放ES中的記錄包含城市,、性別、年齡等原始數(shù)據(jù)(這些字段需要調(diào)用業(yè)務(wù)系統(tǒng)的數(shù)據(jù)進(jìn)行抽?。?,而這些原始數(shù)據(jù)日志文件中并沒有,所以我們并沒有選擇Logstash,。

如果你堅(jiān)持通過Logstash把日志文件的數(shù)據(jù)搬運(yùn)到ES,,我分享3種實(shí)現(xiàn)方式,。

  • 自定義filter:先在Logstash自定義的filter里封裝業(yè)務(wù)數(shù)據(jù),再保存到ES,。因Logstash自定義的filter是使用Ruby語言編寫,,也就是說我們需要使用其他語言編寫業(yè)務(wù)邏輯,因此Logstash自定義filter的方案被我們pass了,。
  • 修改客戶端的埋點(diǎn)邏輯:每次記錄埋點(diǎn)的數(shù)據(jù)發(fā)送到服務(wù)端之前,我們先在客戶端將業(yè)務(wù)的相關(guān)字段提取出來再上傳到服務(wù)端,。這個方法也直接被業(yè)務(wù)端pass了,,理由是后期業(yè)務(wù)側(cè)每更新一次后臺查詢條件,我們就需要重新發(fā)一次版,,實(shí)在太麻煩了,。
  • 修改埋點(diǎn)服務(wù)端的邏輯:每次服務(wù)端在記錄埋點(diǎn)的數(shù)據(jù)發(fā)送到日志文件之前,我們先從數(shù)據(jù)庫獲取業(yè)務(wù)字段組合埋點(diǎn)記錄,。這個方法也被服務(wù)端pass了,,因?yàn)檫@種操作會直接影響每個請求的效率,間接印象用戶體驗(yàn),。

另外,,我們沒選擇logstash還有兩點(diǎn)原因。

  • 日志文件中的數(shù)據(jù)需要同時輸出ES和Hbase兩個輸出源,,因Logstash的多輸出源基于同一個pipeline,,如果1個輸出源出錯了,另1個輸出源也會出錯,,兩者之間會互相影響,。
  • MySQL中需要生成費(fèi)用結(jié)算數(shù)據(jù),而費(fèi)用結(jié)算數(shù)據(jù)需要通過分析埋點(diǎn)的數(shù)據(jù)動態(tài)來計(jì)算,,顯然Logstash并不適合這樣的業(yè)務(wù)場景,,因?yàn)閒ilter可以改變每條數(shù)據(jù)某些字段的值。

在上面的業(yè)務(wù)場景中,,我們最終決定引入了一個計(jì)算框架了,,此時整個解決方案的架構(gòu)圖如下:
高頻數(shù)據(jù)采集請求如何不影響主業(yè)務(wù)(7)

這個方案中就是先通過logstash把日志文件搬運(yùn)到MQ中,再通過實(shí)時計(jì)算框架處理MQ中的數(shù)據(jù),,最后保存處理轉(zhuǎn)換出來的數(shù)據(jù)到持久層中,。

實(shí)際上,引入實(shí)時計(jì)算框架是為了再原始的埋點(diǎn)數(shù)據(jù)中填充業(yè)務(wù)數(shù)據(jù),,并統(tǒng)計(jì)埋點(diǎn)數(shù)據(jù)生成費(fèi)用結(jié)算數(shù)據(jù),,最后分別保存到持久層中。

最后,,關(guān)于Logstash的注意點(diǎn),,我們需要再強(qiáng)調(diào)下,。

Logstash系統(tǒng)是通過Ruby語言編寫的,資源消耗大,,所以官方又推出一個輕量的Filbeat,。我們可以使用Filebeat收集數(shù)據(jù),再通過Logstash進(jìn)行數(shù)據(jù)過濾,。如果你不想使用Logstash的強(qiáng)大過濾功能,,你可以直接使用Filebeat收集日志數(shù)據(jù)發(fā)送給kafka。

但問題又來了,,F(xiàn)ilebeat是使用輪詢的方式采集文件變動,,存在一定(有時候很大)延時,不像Logstash可直接監(jiān)聽文件變動,,所以最后最終我們選擇繼續(xù)使用Logstash,。(因?yàn)槲覀兛傅米≠Y源的消耗)

下面,我們開始討論kafka,、處理框架,。

3、為什么使用Kafka,?

kafka是LinkedIn推出的開源消息中間件,,它天生是為收集日志而設(shè)計(jì),且它具備超高的吞吐量和數(shù)據(jù)量的擴(kuò)展性,,號稱無線堆積,。

根據(jù)LinkedIn官方說法,他們使用3臺便宜的機(jī)器部署kafka,,就能每秒寫入2百萬條記錄,,官方博客有說明,感興趣的可以自行查找一下,。,。。

看到這里,,大家肯定會好奇為什么它的吞吐量這么高,?這里我們就有必要了解kafka的存儲結(jié)構(gòu)了,我們先看一張架構(gòu)示意圖:

高頻數(shù)據(jù)采集請求如何不影響主業(yè)務(wù)(7)

圖片來源:kafka官方文檔:http://kafka./documentation/#log

Kafka 的存儲結(jié)構(gòu)中每個Topic分區(qū)相當(dāng)于1個巨型文件,,而每個巨型文件又是由多個segment小文件組成,。其中,producer負(fù)責(zé)對該巨型文件進(jìn)行“順序?qū)憽?,Consumer負(fù)責(zé)對該文件進(jìn)行“順序讀”,。

這里,我們可以把kafka的存儲架構(gòu)簡單理解為kafka寫數(shù)據(jù)通過追加數(shù)據(jù)到文件尾實(shí)現(xiàn)順序?qū)懀x取數(shù)據(jù)時直接從文件中讀,,好處是讀操作不會阻塞寫操作,,這也是吞吐量大的原因。

另外,,理論上只要磁盤空間足夠,,kafka可以實(shí)現(xiàn)消息無限堆積,因此它特別適合處理日志收集這種場景,,可見我們選擇使用kafka是有一定理論依據(jù)的哦,。

4、使用什么技術(shù)把kafka的數(shù)據(jù)搬運(yùn)到持久層,?

為了把kafka的數(shù)據(jù)搬運(yùn)到持久層,,我們需要使用一個分布式實(shí)時計(jì)算框架,原因有2點(diǎn):

  1. 數(shù)據(jù)量特別大,,為此我們需要使用一個處理框架將上億的埋點(diǎn)數(shù)據(jù)每天進(jìn)行快速分析和處理(且必須使用多個節(jié)點(diǎn)并發(fā)處理才來得及),,再存放到ES,、Hbase和MySQL中,,即大數(shù)據(jù)計(jì)算,因此它有分布式計(jì)算的訴求,。
  2. 業(yè)務(wù)要求實(shí)時查詢統(tǒng)計(jì)報(bào)表數(shù)據(jù),,因此我們需要一個實(shí)時計(jì)算框架處理埋點(diǎn)數(shù)據(jù)。

目前,,市面上流行的分布式實(shí)時計(jì)算框架有3種:Storm,、Spark Stream、Apache Flink,,到底使用哪個好呢,?

我認(rèn)為都可以,這就看公司的具體情況了,,比如公司已經(jīng)使用實(shí)時計(jì)算框架了,,你就不需要再考慮這個問題了,如果公司還沒使用,,那就看個人喜好了,。

我個人偏好Apache Flink,不僅因?yàn)樗阅軓?qiáng)(聽說阿里雙11使用它后,,1秒內(nèi)處理了17億條數(shù)據(jù)),,還因?yàn)樗娜蒎e機(jī)制能保證每條數(shù)據(jù)僅僅處理1次,且它有時間窗口處理功能,。

關(guān)于流處理,、容錯機(jī)制、時間窗口這三個概念,,我們具體展開說明一下,。

在流處理這個過程中,,往往會引發(fā)一系列的問題,比如一條消息處理過程中,,如果系統(tǒng)出現(xiàn)故障該怎么辦,?你會處理嗎?如果重試會不會出現(xiàn)重復(fù)處理,?如果不重復(fù),,消息是否會丟失?你能保證每條消息最多或最少處理幾次,?

在不同流處理框架中采取不同的容錯機(jī)制,,他們也就保證了不一樣的一致性。

  1. At-Most-Once:至多一次,,表示一條消息不管后續(xù)處理成功與否只會被消費(fèi)處理一次,,存在數(shù)據(jù)丟失可能。
  2. Exactly-Once:精確一次,,表示一條消息從其消費(fèi)到后續(xù)的處理成功,,只會發(fā)生一次。
  3. At-Least-Once:至少一次,,表示一條消息從消費(fèi)到后續(xù)的處理成功,,可能會發(fā)生多次,存在重復(fù)消費(fèi)的可能,。

以上三種方式中,,Exactly-Once無疑是最優(yōu)的選擇,因?yàn)樵谡5臉I(yè)務(wù)場景中,,一般只要求消息處理一次,。而Apache Flink的容錯機(jī)制就可以保證所有消息只處理一次(Exactly-Once)的一致性,還能保證系統(tǒng)安全性能,,所以很多人最終都使用它,。

接下來,我們來說說Apache Flink的時間窗口計(jì)算功能,,以下是Apache Flink的一個代碼示例,,它把每個小時里發(fā)生事件的用戶聚合在一個列表中。

final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime);
// alternatively:
// env.setStreamTimeCharacteristic(TimeCharacteristic.IngestionTime);
// env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
DataStream<MyEvent> stream = env.addSource(new FlinkKafkaConsumer09<MyEvent>(topic, schema, props));
stream
    .keyBy( (event) -> event.getUser() )
    .timeWindow(Time.hours(1))
    .reduce( (a, b) -> a.add(b) )
    .addSink(...);

我們知道,,日志中事件發(fā)生的時間有可能與計(jì)算框架處理消息的時間不一致,。

假定實(shí)時計(jì)算框架收到消息的時間是2秒后,比如有一條消息,,這個事件發(fā)生的時間是6:30,,因你接收到消息后處理的時間延后了2秒,即變成了6:32,因此當(dāng)你計(jì)算6:01-6:30的數(shù)據(jù)和,,這條消息并不會計(jì)算在6:01-6:30范圍內(nèi),,這就不符合實(shí)際的業(yè)務(wù)需求了。

在實(shí)際業(yè)務(wù)場景中,,如果需要按照時間窗口統(tǒng)計(jì)數(shù)據(jù),,我們往往是根據(jù)消息的事件時間來計(jì)算。而Apache Flink的特性恰恰是基于消息的事件時間,,而不是基于計(jì)算框架的處理時間,,這也是它的另一個撒手锏。

三,、總結(jié)

本篇文章中,,我們并沒有討論一些特別深入的架構(gòu)設(shè)計(jì)上的注意點(diǎn),主要是闡述技術(shù)選型背后的思考過程,,希望對大家的架構(gòu)思維的提升有所幫助,。

下一篇文章我們來聊聊秒殺架構(gòu),秒殺架構(gòu)是一個綜合性非常強(qiáng)的問題,,并且在面試時經(jīng)常會被問到,,有興趣的朋友可以關(guān)注一下。

來源:https://www./content-4-886651.html

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多