2017-01-18 20 views
0

我在廣告技術領域工作,我們當前的基礎架構使用MySQL來存儲點擊和轉換日誌。到目前爲止,MySQL對我們運行鍼對點擊數據的即席查詢非常有用。 我們正考慮切換到卡桑德拉,因爲我們在高峯時段收到巨大的交通高峯。不僅如此,我們正以非常快的速度增長,並且我們每時每刻都會獲得約500-1000次點擊(持續時間有時會持續20-30分鐘)。 我一直都是可用的選項,到目前爲止,我的研究讓我相信,在寫入性能方面沒有什麼比Cassandra更出色。 我目前正在創建一個數據模型來存儲點擊的過程。 任何點擊的主要成分如下:Cassandra用於存儲點擊日誌

  1. 廣告系列ID
  2. 酒吧ID
  3. 時間戳
  4. 創意ID
  5. 事件代碼(無論它是一個有效的點擊或無效點擊。例如,event_code = 0是一個有效的點擊)

現在,我需要支持以下查詢:

1. SELECT * FROM clicks WHERE campaign_id=? 
2. SELECT * FROM clicks WHERE campaign_id=? AND date_time>=? AND date_time <=? 
3. SELECT * FROM clicks WHERE campaign_id=? AND pub_id=? AND AND date_time>=? AND date_time <=? AND event_code=? 

等 這是很簡單的與MySQL做的,在這之後,我會在一個CSV文件,從這些查詢的所有數據。 不過,如果我是基於第一查詢我的表模型,這將意味着我需要在卡桑德拉創建一個表如下所示:

CREATE TABLE clicks_by_campaign(
    camp_id int, 
    pub_id int, 
    date_time timestamp, 
    creative_id int, 
    event_code int, 
    //other fields like ip, user agent ,device etc, 
    PRIMARY KEY(camp_id,pub_id,date_time,event_code,creative_id)) 

但也有活動,可以有幾百萬行。例如,我們的廣告系列使用特定ID,例如id = 3,其點擊次數超過700萬次。 這不會造成寬行問題嗎?據我所知,所有這些活動數據將作爲一個分區存儲在一臺物理機器上。我的想法是正確的還是我錯過了什麼?請注意,其他查詢也必須得到支持。例如,我可能必須共享特定發佈商的點擊日誌(不管廣告系列ID如何)。在這種情況下,查詢將如下所示:

SELECT * FROM clicks_by_publisher WHERE pub_id=? 

顯然,這將意味着我將不得不被命名爲「clicks_by_publisher」等創建另一個表

我也想指出,我將使用Apache Flink,它可以在1分鐘的時間窗口內分析,彙總和分組點擊信息。這些結果將進一步存儲到MySQL中,以儘可能多地支持臨時查詢。

無論如何,如果有人指出我正確的方向,我將不勝感激。 有沒有其他策略可以使用?我錯過了什麼嗎? 謝謝:)

回答

1

您有幾個選項。三我覺得我可以形容。第一種是指定列如下

campaign_id = PRIMARY_KEY 
event_code = CLUSTER_KEY 
date_time = CLUSTER_KEY 

對集羣密鑰運行大於或等於查詢是可能的。您的查詢將會運行。

你說得對,這將爲每個活動ID創建一個單獨的分區。要解決您的行存儲在一臺物理機器上,您可以創建一個將廣告系列標識鏈接到點擊表中的行標識的不同表格。這會減少存儲在單臺機器上的整體數據。

另一種解決方案是將每個廣告系列ID加上機器ID前綴。這平均分割每臺機器之間的行數。這意味着爲每個查詢創建一個以每個機器ID爲前綴的查詢,但允許增長。

這導致spark。 Spark將處理在多臺機器上運行查詢並自動連接結果,基本上按照我上面描述的方式進行,而無需開發開銷。

與Cassandra自己一起工作時,我選擇了第一個和第二個解決方案的組合,因爲它適合於我正在使用的數據結構。請記住,Cassandra在寫入時非常高效,所以不要過於保守地創建表來幫助過濾查詢和更稀疏地存儲數據。

也許存儲以日期爲前綴的廣告系列ID的哈希點擊將適用於您。 編輯:除非禁用,否則Cassandra將使用Murmur3算法自動散列主鍵。

1

要快速讀取和分配合適的型號您的要求,請使用下表定義 -

CREATE TABLE clicks_by_campaign(
camp_id int, 
createdon bigint, 
pub_id int, 
creative_id int, 
event_code int, 
//other fields like ip, user agent ,device etc, 
PRIMARY KEY((camp_id,createdon),event_code)) 

這將有助於跨分區均勻地分佈數據。這也解決了我們的第二個和第三個查詢 -

2. SELECT * FROM clicks WHERE campaign_id=? AND date_time>=? AND date_time <=? 
    Query will be - 
SELECT * FROM clicks_by_campaign WHERE token(camp_id, createdon) > token(100, '1111111111111') AND token(camp_id, createdon) <= token(100, '22222222222222') 


3. SELECT * FROM clicks WHERE campaign_id=? AND pub_id=? AND AND date_time>=? AND date_time <=? AND event_code=? 
The query will be - 
SELECT * FROM clicks_by_campaign WHERE token(camp_id, createdon) > token(100, '1111111111111') AND token(camp_id, createdon) <= token(100, '22222222222222') AND event_code=10 

首先查詢 -

1. SELECT * FROM clicks WHERE campaign_id=? 

這真是一個卡桑德拉反模式。我會做什麼,批量處理活動數據,每小時 - 每週 - 每年。再次考慮活動ID,我們是否必須一次處理所有數據。 'clicks_by_publisher'也一樣。

編輯使用分區鍵1個

Could you elaborate on what you mean by 'token' ? 

卡桑德拉分區行。在上面的表定義中,我們組合了camp_id和createdon值(camp_id和created作爲RDBMS中的組合主鍵),以形成分區鍵。 cassandra分區程序計算結合camp_id和createdon的散列值,並確定該行所經過的分區。爲了檢索同一行,分區器需要重新計算散列值。函數toke(),這樣做。

時間戳代表點擊事件發生的時間,該值以毫秒爲單位。使用createdon(鍵入long)將有助於在分區間平均分配行。

例如,對於插入語句

1. INSERT INTO clicks_by_campaign (camp_id,createdon ,....) values 100,1111111111111,......) the calculated hash, lets say 111 (combining values 100,1111111111111) -- this will go in partition 1 
2. INSERT INTO clicks_by_campaign (camp_id,createdon ,....) values (100,2222222222222,......) the calculated hash, lets say 222 (combining values 100,2222222222222) -- this will go in partition 2 

Java有API來轉換日期爲毫秒。以毫秒錶示的日期可以使用任何時區轉換爲任何格式。

事實上,您的用例是設計時間序列數據模型的合適人選。

+0

感謝您的回覆。你能詳細說明'token'是什麼意思嗎?此外,在我看來,你建議通過時間戳分區活動數據(所以如果我們得到5次點擊1個時間戳,這將構成一個5行分區)。這實際上是實現它的最好方式,但我無法想象如果我想在特定日期獲取某個廣告系列的點擊詳情,請運行60 * 60 * 24查詢。 – Ankush92

+0

@ Ankush92添加了更多的細節來回答。 – Gunwant

+0

感謝您的解釋。我會更多地考慮這一點。真的很感激它! – Ankush92