亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

Apache Cassandra是大規(guī)模管理 IoT 和時間序列數(shù)據(jù)的可靠選擇。在 Cassandra 中存儲、查詢和分析 IoT 設(shè)備生成的時間序列的最流行用例已得到很好的理解和記錄。通常,時間序列是根據(jù)其源 IoT 設(shè)備存儲和查詢的。但是,還有另一類 IoT? 應(yīng)用程序需要快速訪問由一組 IoT 設(shè)備基于已知狀態(tài)生成的最新數(shù)據(jù)。此類應(yīng)用程序需要回答的問題是:哪些物聯(lián)網(wǎng)設(shè)備或傳感器當(dāng)前正在報告特定狀態(tài)?在這篇博文中,我們將重點(diǎn)關(guān)注這個問題,并提供五種可能的數(shù)據(jù)建模解決方案,以便在 Cassandra 中有效地回答這個問題。

介紹

物聯(lián)網(wǎng) (IoT) 正在生成大量需要存儲、查詢和分析的時間序列數(shù)據(jù)。Apache Cassandra 是這項(xiàng)任務(wù)的絕佳選擇:不僅因?yàn)樗乃俣取⒖煽啃院涂蓴U(kuò)展性,還因?yàn)樗膬?nèi)部數(shù)據(jù)模型內(nèi)置了對時間排序數(shù)據(jù)的支持。

在 Cassandra 中,時間序列通常由源(例如,IoT 設(shè)備或傳感器)或主題(例如,參數(shù)或度量)存儲和檢索。有很多很好的資源非常詳細(xì)地涵蓋了這個主題,包括這個會議演示視頻,以及用于傳感器數(shù)據(jù)和時間序列的即用型 Cassandra 數(shù)據(jù)模型。

在這篇文章中,我們研究了一類相關(guān)的物聯(lián)網(wǎng)用例,它們需要管理來自許多物聯(lián)網(wǎng)設(shè)備的最新數(shù)據(jù)的快照。此外,需要根據(jù)物聯(lián)網(wǎng)設(shè)備報告的特定狀態(tài)來查詢或過濾這樣的快照。換句話說,我們應(yīng)該能夠在 Cassandra 中快速回答這個問題:哪些物聯(lián)網(wǎng)設(shè)備當(dāng)前正在報告特定狀態(tài)?對于許多現(xiàn)實(shí)生活中的用例,這個問題聽起來更像是:

  • 智能家居中當(dāng)前打開(關(guān)閉)哪些燈?
  • 停車結(jié)構(gòu)中當(dāng)前有哪些停車位被占用(空置)?
  • 當(dāng)前在特定位置附近有哪些車輛可用(不可用)?
  • 當(dāng)前在某個區(qū)域觸發(fā)(激活、禁用)哪些安全警報?
  • 建筑物中當(dāng)前打開(關(guān)閉、鎖定、解鎖)哪些門?
  • 哪些火災(zāi)探測傳感器當(dāng)前報告?zhèn)鞲衅骶W(wǎng)絡(luò)中的異常(正常待機(jī)、錯誤)狀態(tài)?

在下文中,我們更正式地定義了這個問題,并通過示例 CQL 實(shí)現(xiàn)提出了五個實(shí)用的解決方案。

問題定義

給定一組 IoT 設(shè)備或傳感器,這些設(shè)備或傳感器生成包含時間戳、數(shù)據(jù)點(diǎn)和狀態(tài)的按時間排序的事件序列,找到所有 IoT 設(shè)備報告的具有已知狀態(tài)的最新事件。這個問題的三個關(guān)鍵組成部分如下圖所示,描述如下:

  1. 輸入由物聯(lián)網(wǎng)設(shè)備生成的時間序列組成。時間序列通常存儲在一個或多個 Cassandra 表中。
  2. 中間視圖是 IoT 設(shè)備報告的僅最新事件的快照。可以單獨(dú)顯式存儲最新事件,也可以根據(jù)輸入動態(tài)計(jì)算它們。
  3. 最終結(jié)果是所有具有已知狀態(tài)的最新事件。具有相同狀態(tài)的最新事件應(yīng)該存儲在一起或易于計(jì)算。

基于狀態(tài)管理最新的 IoT 事件

我們確定了基于狀態(tài)管理最新物聯(lián)網(wǎng)事件的幾個挑戰(zhàn):

  • 最新事件的快照不斷發(fā)展。可能需要額外的努力來增量捕獲任何更改。
  • 事件發(fā)生的頻率通常是不可預(yù)測的。僅基于事件的時間戳組件可能難以對事件進(jìn)行分區(qū)和組織。
  • 一個狀態(tài)通常只能采用幾個唯一值。基于低基數(shù)列對數(shù)據(jù)進(jìn)行分區(qū)和索引可能會導(dǎo)致大分區(qū)。

我們使用以下運(yùn)行示例作為起點(diǎn)。表 events_by_device 是輸入。這張具有多行分區(qū)的表旨在存儲時間序列,這樣每個分區(qū)對應(yīng)一個設(shè)備,分區(qū)中的行表示具有時間戳、狀態(tài)和值的事件。每個分區(qū)中的事件始終按其時間戳降序排序。該表實(shí)質(zhì)上每個分區(qū)存儲一個時間序列。我們將五個事件插入表中并檢索一個設(shè)備的時間序列。此外,在第二個查詢中,我們證明可以動態(tài)計(jì)算所有設(shè)備的所有最新事件。不幸的是,我們不應(yīng)該依賴這個查詢來解決問題:它可能會變得非常昂貴,因?yàn)樗L問表中的每個分區(qū)。

架構(gòu):

CQL

-- All events by deviceCREATE TABLE events_by_device (    device_id  UUID,    timestamp  TIMESTAMP,    state      TEXT,    value      TEXT,    PRIMARY KEY((device_id), timestamp)) WITH CLUSTERING ORDER BY (timestamp DESC);

 

數(shù)據(jù):

CQL

-- Event 1-1INSERT INTO events_by_device        (device_id, timestamp, state, value)VALUES (11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 01:11:11', 'on', 'event 1-1');-- Event 1-2INSERT INTO events_by_device        (device_id, timestamp, state, value)VALUES (11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 02:22:22', 'off', 'event 1-2');-- Event 1-3INSERT INTO events_by_device        (device_id, timestamp, state, value)VALUES (11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 03:33:33', 'on', 'event 1-3');-- Event 2-1INSERT INTO events_by_device        (device_id, timestamp, state, value)VALUES (22222222-aaaa-bbbb-cccc-12345678abcd,         '2021-02-02 01:11:11', 'off', 'event 2-1');-- Event 3-1INSERT INTO events_by_device        (device_id, timestamp, state, value)VALUES (33333333-aaaa-bbbb-cccc-12345678abcd,         '2021-03-03 01:11:11', 'off', 'event 3-1');

 

查詢:

CQL

-- Find all events for a deviceSELECT device_id, timestamp, state, valueFROM   events_by_deviceWHERE  device_id = 11111111-aaaa-bbbb-cccc-12345678abcd; device_id                            | timestamp                       | state | value--------------------------------------+---------------------------------+-------+----------- 11111111-aaaa-bbbb-cccc-12345678abcd | 2021-01-01 03:33:33.000000+0000 |    on | event 1-3 11111111-aaaa-bbbb-cccc-12345678abcd | 2021-01-01 02:22:22.000000+0000 |   off | event 1-2 11111111-aaaa-bbbb-cccc-12345678abcd | 2021-01-01 01:11:11.000000+0000 |    on | event 1-1-- Find the latest events for all devicesSELECT device_id, timestamp, state, valueFROM   events_by_devicePER PARTITION LIMIT 1; device_id                            | timestamp                       | state | value--------------------------------------+---------------------------------+-------+----------- 33333333-aaaa-bbbb-cccc-12345678abcd | 2021-03-03 01:11:11.000000+0000 |   off | event 3-1 22222222-aaaa-bbbb-cccc-12345678abcd | 2021-02-02 01:11:11.000000+0000 |   off | event 2-1 11111111-aaaa-bbbb-cccc-12345678abcd | 2021-01-01 03:33:33.000000+0000 |    on | event 1-3

 

請注意,我們可以假設(shè)每個設(shè)備的事件數(shù)不超過 100,000。否則,我們可能不得不通過在其分區(qū)鍵定義中引入另一列來進(jìn)一步拆分表 events_by_device 中的分區(qū)。由于這對于我們在這篇文章中解決的問題并不重要,所以讓我們保持簡單。

鑒于問題定義和IoT 事件的運(yùn)行 CQL 示例,我們準(zhǔn)備描述具有不同特征的五種解決方案。

解決方案一:物化視圖

第一個解決方案需要一個新表和一個物化視圖。表 latest_events_by_device 是一個單行分區(qū)表,其中每個分區(qū)對應(yīng)一個設(shè)備,每一行對應(yīng)最新的已知事件。此表的目的是僅獲取 IoT 設(shè)備報告的最新事件的快照。該表也是物化視圖 latest_events_by_state 的基表,可以使用狀態(tài)查詢最新事件。

請注意,完全相同的數(shù)據(jù)被插入到表 events_by_device 和 latest_events_by_device 中。但是,對于后者,插入變?yōu)楦虏迦耄瑢⑿懈聻樽钚率录?/p>

架構(gòu):

CQL

-- Latest known events by deviceCREATE TABLE latest_events_by_device (    device_id  UUID,    timestamp  TIMESTAMP,    state      TEXT,    value      TEXT,    PRIMARY KEY((device_id)));-- Latest events by stateCREATE MATERIALIZED VIEW latest_events_by_state AS   SELECT * FROM latest_events_by_device  WHERE state IS NOT NULL AND device_id IS NOT NULLPRIMARY KEY ((state), device_id);

 

數(shù)據(jù):

CQL

-- Event 1-1INSERT INTO latest_events_by_device        (device_id, timestamp, state, value)VALUES (11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 01:11:11', 'on', 'event 1-1');-- Event 1-2INSERT INTO latest_events_by_device        (device_id, timestamp, state, value)VALUES (11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 02:22:22', 'off', 'event 1-2');-- Event 1-3INSERT INTO latest_events_by_device        (device_id, timestamp, state, value)VALUES (11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 03:33:33', 'on', 'event 1-3');-- Event 2-1INSERT INTO latest_events_by_device        (device_id, timestamp, state, value)VALUES (22222222-aaaa-bbbb-cccc-12345678abcd,         '2021-02-02 01:11:11', 'off', 'event 2-1');-- Event 3-1INSERT INTO latest_events_by_device        (device_id, timestamp, state, value)VALUES (33333333-aaaa-bbbb-cccc-12345678abcd,         '2021-03-03 01:11:11', 'off', 'event 3-1');

 

查詢:

CQL

-- Find all the latest events with state 'on'SELECT state, device_id, timestamp, valueFROM   latest_events_by_stateWHERE  state = 'on'; state | device_id                            | timestamp                       | value-------+--------------------------------------+---------------------------------+-----------    on | 11111111-aaaa-bbbb-cccc-12345678abcd | 2021-01-01 03:33:33.000000+0000 | event 1-3-- Find all the latest events with state 'off'SELECT state, device_id, timestamp, valueFROM   latest_events_by_stateWHERE  state = 'off'; state | device_id                            | timestamp                       | value-------+--------------------------------------+---------------------------------+-----------   off | 22222222-aaaa-bbbb-cccc-12345678abcd | 2021-02-02 01:11:11.000000+0000 | event 2-1   off | 33333333-aaaa-bbbb-cccc-12345678abcd | 2021-03-03 01:11:11.000000+0000 | event 3-1

 

物化視圖解決方案具有以下特點(diǎn):

  • 適用性:基于狀態(tài)的查詢返回 100K 行/100MB 或更少的數(shù)據(jù)。
  • 優(yōu)點(diǎn):視圖是自動維護(hù)的;完美的表現(xiàn)。
  • 缺點(diǎn):物化視圖有一些限制;數(shù)據(jù)分布可能會出現(xiàn)偏差。

為了支持多租戶,我們可以把表的主鍵改成PRIMARY KEY((tenant, device_id))或者PRIMARY KEY((tenant), device_id),物化視圖的主鍵改成PRIMARY KEY((tenant, state), device_id )。多租戶也可能有助于改善數(shù)據(jù)分布。

只要您了解并愿意抵消物化視圖的限制,此數(shù)據(jù)模型就可以成為許多應(yīng)用程序的簡單、有效和高效的選擇。這種數(shù)據(jù)模型的另一個不太明顯的優(yōu)勢是從 Apache Pulsar 或 Apache Kafka 等事件流平臺提供數(shù)據(jù)是多么容易。所有事件都可以轉(zhuǎn)到基表,而物化視圖負(fù)責(zé)其余的事情。

方案二:二級索引

第二種解決方案需要一個新表和一個二級索引。該表與物化視圖解決方案中的表相同。表 latest_events_by_device 是一個單行分區(qū)表,其中每個分區(qū)對應(yīng)一個設(shè)備,每一行對應(yīng)最新的已知事件。此表的目的是僅獲取 IoT 設(shè)備報告的最新事件的快照。為該表創(chuàng)建二級索引latest_events_by_state_2i,用于根據(jù)狀態(tài)查詢最新事件。

再一次,完全相同的數(shù)據(jù)被插入到表 events_by_device 和 latest_events_by_device 中。但是,對于后者,插入變?yōu)楦虏迦耄瑢⑿懈聻樽钚率录?/p>

架構(gòu):

CQL

-- Latest known events by deviceCREATE TABLE latest_events_by_device (    device_id  UUID,    timestamp  TIMESTAMP,    state      TEXT,    value      TEXT,    PRIMARY KEY((device_id)));-- Latest events by stateCREATE INDEX latest_events_by_state_2i ON latest_events_by_device (state);

 

數(shù)據(jù):

CQL

-- Event 1-1INSERT INTO latest_events_by_device        (device_id, timestamp, state, value)VALUES (11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 01:11:11', 'on', 'event 1-1');-- Event 1-2INSERT INTO latest_events_by_device        (device_id, timestamp, state, value)VALUES (11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 02:22:22', 'off', 'event 1-2');-- Event 1-3INSERT INTO latest_events_by_device        (device_id, timestamp, state, value)VALUES (11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 03:33:33', 'on', 'event 1-3');-- Event 2-1INSERT INTO latest_events_by_device        (device_id, timestamp, state, value)VALUES (22222222-aaaa-bbbb-cccc-12345678abcd,         '2021-02-02 01:11:11', 'off', 'event 2-1');-- Event 3-1INSERT INTO latest_events_by_device        (device_id, timestamp, state, value)VALUES (33333333-aaaa-bbbb-cccc-12345678abcd,         '2021-03-03 01:11:11', 'off', 'event 3-1');

 

查詢:

CQL

-- Find all the latest events with state 'on'SELECT state, device_id, timestamp, valueFROM   latest_events_by_deviceWHERE  state = 'on'; state | device_id                            | timestamp                       | value-------+--------------------------------------+---------------------------------+-----------    on | 11111111-aaaa-bbbb-cccc-12345678abcd | 2021-01-01 03:33:33.000000+0000 | event 1-3-- Find all the latest events with state 'off'SELECT state, device_id, timestamp, valueFROM   latest_events_by_deviceWHERE  state = 'off'; state | device_id                            | timestamp                       | value-------+--------------------------------------+---------------------------------+-----------   off | 33333333-aaaa-bbbb-cccc-12345678abcd | 2021-03-03 01:11:11.000000+0000 | event 3-1   off | 22222222-aaaa-bbbb-cccc-12345678abcd | 2021-02-02 01:11:11.000000+0000 | event 2-1

 

二級索引方案具有以下特點(diǎn):

  • 適用性:基于狀態(tài)的查詢返回 100K 行/100MBs 或更多的數(shù)據(jù);基于狀態(tài)的查詢很少執(zhí)行。
  • 優(yōu)點(diǎn):在檢索大型結(jié)果集時,可以更好地在集群中的節(jié)點(diǎn)之間分配查詢工作負(fù)載。
  • 缺點(diǎn):二級索引有一些限制;對于實(shí)時應(yīng)用程序,性能可能會變得不令人滿意。

在某些情況下,這種數(shù)據(jù)模型可能是一個合理的選擇。特別是,當(dāng)通過將表主鍵更改為 PRIMARY KEY((tenant), device_id) 來引入多租戶時,我們可以達(dá)到使用二級索引進(jìn)行實(shí)時事務(wù)查詢的最佳時機(jī)。那是在基于分區(qū)鍵和查詢謂詞中指定的索引列從大型多行分區(qū)中檢索行時。

解決方案 3:狀態(tài)分區(qū)表

第三種解決方案依賴表 latest_events_by_state 使用狀態(tài)來組織和查詢最新事件。每次向該表中插入具有某種狀態(tài)的事件時,都必須刪除同一物聯(lián)網(wǎng)設(shè)備的具有其他狀態(tài)的任何過時事件。在我們的示例中,每個事件都有一個插入和一個刪除,因?yàn)槲覀冎挥袃蓚€唯一狀態(tài)。如果我們有三種可能的狀態(tài),每個新事件將導(dǎo)致一次插入和兩次刪除。

架構(gòu):

CQL

-- Latest events by stateCREATE TABLE latest_events_by_state (    state      TEXT,    device_id  UUID,    timestamp  TIMESTAMP,    value      TEXT,    PRIMARY KEY((state), device_id));

 

數(shù)據(jù):

CQL

-- Event 1-1INSERT INTO latest_events_by_state        (state, device_id, timestamp, value)VALUES ('on', 11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 01:11:11', 'event 1-1');DELETE FROM latest_events_by_state WHERE state = 'off' AND      device_id = 11111111-aaaa-bbbb-cccc-12345678abcd;-- Event 1-2INSERT INTO latest_events_by_state        (state, device_id, timestamp, value)VALUES ('off', 11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 02:22:22', 'event 1-2');DELETE FROM latest_events_by_state WHERE state = 'on' AND      device_id = 11111111-aaaa-bbbb-cccc-12345678abcd;-- Event 1-3INSERT INTO latest_events_by_state        (state, device_id, timestamp, value)VALUES ('on', 11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 03:33:33', 'event 1-3');DELETE FROM latest_events_by_state WHERE state = 'off' AND      device_id = 11111111-aaaa-bbbb-cccc-12345678abcd;-- Event 2-1INSERT INTO latest_events_by_state        (state, device_id, timestamp, value)VALUES ('off', 22222222-aaaa-bbbb-cccc-12345678abcd,         '2021-02-02 01:11:11', 'event 2-1');DELETE FROM latest_events_by_state WHERE state = 'on' AND      device_id = 22222222-aaaa-bbbb-cccc-12345678abcd;-- Event 3-1INSERT INTO latest_events_by_state        (state, device_id, timestamp, value)VALUES ('off', 33333333-aaaa-bbbb-cccc-12345678abcd,         '2021-03-03 01:11:11', 'event 3-1');DELETE FROM latest_events_by_state WHERE state = 'on' AND      device_id = 33333333-aaaa-bbbb-cccc-12345678abcd;

 

查詢:

CQL

-- Find all the latest events with state 'on'SELECT state, device_id, timestamp, valueFROM   latest_events_by_stateWHERE  state = 'on'; state | device_id                            | timestamp                       | value-------+--------------------------------------+---------------------------------+-----------    on | 11111111-aaaa-bbbb-cccc-12345678abcd | 2021-01-01 03:33:33.000000+0000 | event 1-3-- Find all the latest events with state 'off'SELECT state, device_id, timestamp, valueFROM   latest_events_by_stateWHERE  state = 'off'; state | device_id                            | timestamp                       | value-------+--------------------------------------+---------------------------------+-----------   off | 22222222-aaaa-bbbb-cccc-12345678abcd | 2021-02-02 01:11:11.000000+0000 | event 2-1   off | 33333333-aaaa-bbbb-cccc-12345678abcd | 2021-03-03 01:11:11.000000+0000 | event 3-1

 

狀態(tài)分區(qū)表解決方案具有以下特點(diǎn):

  • 適用性:基于狀態(tài)的查詢返回 100K 行/100MB 或更少的數(shù)據(jù)。
  • 優(yōu)點(diǎn):出色的性能。
  • 缺點(diǎn):需要額外的刪除來維護(hù)表;可能需要采取措施防止與墓碑有關(guān)的問題;數(shù)據(jù)分布可能會出現(xiàn)偏差。

在大多數(shù)情況下,這三個缺點(diǎn)都不應(yīng)被視為嚴(yán)重障礙。額外的刪除相當(dāng)于額外的寫入,Cassandra 可以輕松擴(kuò)展以處理更多寫入。鑒于插入和刪除一次又一次地應(yīng)用于相同的行,墓碑很可能在 MemTable 而不是 SSTables 中得到解決,這可以大大減少墓碑的總數(shù)。例如,對于一個給定的物聯(lián)網(wǎng)設(shè)備,即使是頻繁的狀態(tài)更新都命中同一個 MemTable 也只能導(dǎo)致一個墓碑。我們?nèi)匀唤ㄗh監(jiān)控表指標(biāo)以排除任何潛在問題。最后但同樣重要的是,數(shù)據(jù)分布取決于數(shù)據(jù)和應(yīng)用程序特征。在本文的最后一個解決方案中,我們完全控制了數(shù)據(jù)分布。

我們可以通過將表主鍵更改為 PRIMARY KEY((tenant, state), device_id) 輕松支持多個租戶。多租戶也可能有助于改善數(shù)據(jù)分布。總體而言,在性能方面,該解決方案應(yīng)該可以與物化視圖解決方案相媲美。

解決方案 4:多個表

第四種解決方案的特點(diǎn)是每個州都有一個單獨(dú)的表格。對表
latest_on_events_by_device 的每次插入都必須伴隨著從表 latest_off_events_by_device 中刪除,反之亦然。這是為了確保最新事件始終取消同一設(shè)備的任何具有不同狀態(tài)的過時事件。對表的基于狀態(tài)的查詢可能會變得非常昂貴,因?yàn)樗鼈儽仨殥呙璞碇械乃蟹謪^(qū)。

架構(gòu):

CQL

-- Latest 'on' events by deviceCREATE TABLE latest_on_events_by_device (    device_id  UUID,    timestamp  TIMESTAMP,    value      TEXT,    PRIMARY KEY((device_id)));-- Latest 'off' events by deviceCREATE TABLE latest_off_events_by_device (    device_id  UUID,    timestamp  TIMESTAMP,    value      TEXT,    PRIMARY KEY((device_id)));

 

數(shù)據(jù):

CQL

-- Event 1-1INSERT INTO latest_on_events_by_device        (device_id, timestamp, value)VALUES (11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 01:11:11', 'event 1-1');DELETE FROM latest_off_events_by_device WHERE device_id = 11111111-aaaa-bbbb-cccc-12345678abcd;-- Event 1-2INSERT INTO latest_off_events_by_device        (device_id, timestamp, value)VALUES (11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 02:22:22', 'event 1-2');DELETE FROM latest_on_events_by_device WHERE device_id = 11111111-aaaa-bbbb-cccc-12345678abcd;-- Event 1-3INSERT INTO latest_on_events_by_device        (device_id, timestamp, value)VALUES (11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 03:33:33', 'event 1-3');DELETE FROM latest_off_events_by_device WHERE device_id = 11111111-aaaa-bbbb-cccc-12345678abcd;-- Event 2-1INSERT INTO latest_off_events_by_device        (device_id, timestamp, value)VALUES (22222222-aaaa-bbbb-cccc-12345678abcd,         '2021-02-02 01:11:11', 'event 2-1');DELETE FROM latest_on_events_by_device WHERE device_id = 22222222-aaaa-bbbb-cccc-12345678abcd;-- Event 3-1INSERT INTO latest_off_events_by_device        (device_id, timestamp, value)VALUES (33333333-aaaa-bbbb-cccc-12345678abcd,         '2021-03-03 01:11:11', 'event 3-1');DELETE FROM latest_on_events_by_device WHERE device_id = 33333333-aaaa-bbbb-cccc-12345678abcd;

 

查詢:

CQL

-- Find all the latest events with state 'on'SELECT device_id, timestamp, valueFROM   latest_on_events_by_device; device_id                            | timestamp                       | value--------------------------------------+---------------------------------+----------- 11111111-aaaa-bbbb-cccc-12345678abcd | 2021-01-01 03:33:33.000000+0000 | event 1-3-- Find all the latest events with state 'off'SELECT device_id, timestamp, valueFROM   latest_off_events_by_device; device_id                            | timestamp                       | value--------------------------------------+---------------------------------+----------- 33333333-aaaa-bbbb-cccc-12345678abcd | 2021-03-03 01:11:11.000000+0000 | event 3-1 22222222-aaaa-bbbb-cccc-12345678abcd | 2021-02-02 01:11:11.000000+0000 | event 2-1

 

多表解決方案具有以下特點(diǎn):

  • 適用性:基于狀態(tài)的查詢返回 100K 行/100MBs 或更多的數(shù)據(jù);基于狀態(tài)的查詢很少執(zhí)行。
  • 優(yōu)點(diǎn):在檢索大型結(jié)果集時,可以更好地在集群中的節(jié)點(diǎn)之間分配查詢工作負(fù)載。
  • 缺點(diǎn):實(shí)時應(yīng)用程序的性能可能無法令人滿意;需要額外的刪除來維護(hù)表;可能需要采取措施防止與墓碑有關(guān)的問題。

該方案在查詢性能上與二級索引方案不相上下。可以通過將表主鍵更改為 PRIMARY KEY((tenant, device_id)) 或 PRIMARY KEY((tenant), device_id) 來支持多個租戶。雖然我們在實(shí)踐中不推薦這種解決方案,但這種數(shù)據(jù)模型真正有趣的是它如何為接下來討論的可定制分區(qū)做好準(zhǔn)備。

解決方案 5:可自定義的分區(qū)

我們的最終解決方案基于為每個狀態(tài)使用單獨(dú)的表的想法。但是,這一次,我們使用人工桶對表進(jìn)行分區(qū)。桶值很容易使用來自設(shè)備 UUID 標(biāo)識符的用戶定義函數(shù)散列來計(jì)算。在此示例中,該函數(shù)從 UUID 文字中提取前三位,將生成的十六進(jìn)制數(shù)轉(zhuǎn)換為十進(jìn)制數(shù),并返回十進(jìn)制數(shù)除以 3 的余數(shù)。因此,最多可以有三個桶或每個表的分區(qū),值為 0、1 或 2。在此示例中,我們所有的設(shè)備標(biāo)識符都映射到存儲桶 0 只是巧合。由于版本 4 UUID是隨機(jī)生成的,因此對于大量事件,數(shù)據(jù)應(yīng)該或多或少均勻分布在三個存儲桶中。

與之前的數(shù)據(jù)模型類似,每次對表
latest_on_events_by_bucket 的插入都必須伴隨著從表 latest_off_events_by_bucket 中刪除,反之亦然。基于狀態(tài)的查詢的性能取決于分區(qū),并且分區(qū)是可定制的。

架構(gòu):

CQL

-- Custom hash functionCREATE FUNCTION hash(id UUID) RETURNS NULL ON NULL INPUT RETURNS INT LANGUAGE JAVA AS 'return Integer.parseInt(id.toString().substring(0,3),16) % 3;';-- Latest 'on' events by deviceCREATE TABLE latest_on_events_by_bucket (    bucket     INT,    device_id  UUID,    timestamp  TIMESTAMP,    value      TEXT,    PRIMARY KEY((bucket), device_id));-- Latest 'off' events by deviceCREATE TABLE latest_off_events_by_bucket (    bucket     INT,    device_id  UUID,    timestamp  TIMESTAMP,    value      TEXT,    PRIMARY KEY((bucket), device_id));

 

數(shù)據(jù):

CQL

-- Event 1-1INSERT INTO latest_on_events_by_bucket        (bucket, device_id, timestamp, value)VALUES (hash(11111111-aaaa-bbbb-cccc-12345678abcd),         11111111-aaaa-bbbb-cccc-12345678abcd,        '2021-01-01 01:11:11', 'event 1-1');DELETE FROM latest_off_events_by_bucket WHERE bucket = hash(11111111-aaaa-bbbb-cccc-12345678abcd) AND       device_id = 11111111-aaaa-bbbb-cccc-12345678abcd;-- Event 1-2INSERT INTO latest_off_events_by_bucket        (bucket, device_id, timestamp, value)VALUES (hash(11111111-aaaa-bbbb-cccc-12345678abcd),        11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 02:22:22', 'event 1-2');DELETE FROM latest_on_events_by_bucket WHERE bucket = hash(11111111-aaaa-bbbb-cccc-12345678abcd) AND       device_id = 11111111-aaaa-bbbb-cccc-12345678abcd;-- Event 1-3INSERT INTO latest_on_events_by_bucket        (bucket, device_id, timestamp, value)VALUES (hash(11111111-aaaa-bbbb-cccc-12345678abcd),        11111111-aaaa-bbbb-cccc-12345678abcd,         '2021-01-01 03:33:33', 'event 1-3');DELETE FROM latest_off_events_by_bucket WHERE bucket = hash(11111111-aaaa-bbbb-cccc-12345678abcd) AND       device_id = 11111111-aaaa-bbbb-cccc-12345678abcd;-- Event 2-1INSERT INTO latest_off_events_by_bucket        (bucket, device_id, timestamp, value)VALUES (hash(22222222-aaaa-bbbb-cccc-12345678abcd),        22222222-aaaa-bbbb-cccc-12345678abcd,         '2021-02-02 01:11:11', 'event 2-1');DELETE FROM latest_on_events_by_bucket WHERE bucket = hash(22222222-aaaa-bbbb-cccc-12345678abcd) AND       device_id = 22222222-aaaa-bbbb-cccc-12345678abcd;-- Event 3-1INSERT INTO latest_off_events_by_bucket        (bucket, device_id, timestamp, value)VALUES (hash(33333333-aaaa-bbbb-cccc-12345678abcd),        33333333-aaaa-bbbb-cccc-12345678abcd,         '2021-03-03 01:11:11', 'event 3-1');DELETE FROM latest_on_events_by_bucket WHERE bucket = hash(33333333-aaaa-bbbb-cccc-12345678abcd) AND       device_id = 33333333-aaaa-bbbb-cccc-12345678abcd;

 

查詢:

CQL

-- Find all the latest events with state 'on'SELECT bucket, device_id, timestamp, valueFROM   latest_on_events_by_bucketWHERE  bucket IN (0,1,2); bucket | device_id                            | timestamp                       | value--------+--------------------------------------+---------------------------------+-----------      0 | 11111111-aaaa-bbbb-cccc-12345678abcd | 2021-01-01 03:33:33.000000+0000 | event 1-3-- Find all the latest events with state 'off'SELECT bucket, device_id, timestamp, valueFROM   latest_off_events_by_bucketWHERE  bucket IN (0,1,2); bucket | device_id                            | timestamp                       | value--------+--------------------------------------+---------------------------------+-----------      0 | 22222222-aaaa-bbbb-cccc-12345678abcd | 2021-02-02 01:11:11.000000+0000 | event 2-1      0 | 33333333-aaaa-bbbb-cccc-12345678abcd | 2021-03-03 01:11:11.000000+0000 | event 3-1

 

可定制的分區(qū)方案具有以下特點(diǎn):

  • 適用性:定制時可滿足不同要求。
  • 優(yōu)點(diǎn):靈活性;可以通過自定義分區(qū)來優(yōu)化性能。
  • 缺點(diǎn):必須提供良好的分區(qū)功能;需要額外的刪除來維護(hù)表;可能需要采取措施防止與墓碑有關(guān)的問題。

選擇一個好的分區(qū)函數(shù)是一個很好的問題。雖然這可能會增加一點(diǎn)復(fù)雜性,但該解決方案可以完全控制數(shù)據(jù)分區(qū)和查詢性能。找到一個好的分區(qū)函數(shù)將取決于特定的數(shù)據(jù)和應(yīng)用程序要求,并且可能需要一些經(jīng)驗(yàn)和實(shí)驗(yàn)。例如,從 1 個分區(qū)檢索 100 行通常比從 10 個分區(qū)檢索 100 行快,但從 1 個分區(qū)檢索 1,000,000 行通常比從 10 個分區(qū)檢索 1,000,000 行慢。接下來,額外的刪除相當(dāng)于額外的寫入,Cassandra 可以輕松擴(kuò)展以處理更多寫入。

鑒于插入和刪除一次又一次地應(yīng)用于相同的行,墓碑很可能在 MemTable 而不是 SSTables 中得到解決,這可以大大減少墓碑的總數(shù)。例如,對于一個給定的物聯(lián)網(wǎng)設(shè)備,即使是頻繁的狀態(tài)更新都命中同一個 MemTable 也只能導(dǎo)致一個墓碑。我們?nèi)匀唤ㄗh監(jiān)控表指標(biāo)以排除任何潛在問題。最后但同樣重要的是,數(shù)據(jù)分布取決于數(shù)據(jù)和應(yīng)用程序特征。在本文的最后一個解決方案中,我們完全控制了數(shù)據(jù)分布。

這種數(shù)據(jù)模型提供了極大的靈活性。通過將每個表的主鍵更改為 PRIMARY KEY((tenant, bucket), device_id) 可以實(shí)現(xiàn)多租戶。更重要的是,可以更改分區(qū)函數(shù)以增加或減少分區(qū)的數(shù)量。檢索較小結(jié)果集的查詢應(yīng)訪問較少數(shù)量的分區(qū)以獲得更好的性能。檢索更大結(jié)果集的查詢應(yīng)訪問更多分區(qū)以更好地分配工作負(fù)載。可以針對不同的狀態(tài)和租戶使用不同的功能以實(shí)現(xiàn)最佳性能。更好的分區(qū)應(yīng)該會帶來更好的性能。

結(jié)論

我們定義了基于狀態(tài)管理最新物聯(lián)網(wǎng)事件的問題,確定了它的挑戰(zhàn),并描述了如何在 Apache Cassandra 中使用五種不同的數(shù)據(jù)模型來解決它。我們陳述了每個數(shù)據(jù)模型的適用性、優(yōu)缺點(diǎn)。我們的最終建議是關(guān)注物化視圖、狀態(tài)分區(qū)表和可自定義的分區(qū)數(shù)據(jù)模型。選擇前兩個是因?yàn)樗鼈兒唵我子谩.?dāng)其他選項(xiàng)用盡時,考慮可定制的分區(qū)以獲得最大的靈活性。最后,開放探索新的可能解決方案,這些解決方案可能會將一些計(jì)算推向應(yīng)用程序或依賴專門的搜索索引和其他技術(shù)。

值得一提的是,這篇博文的動機(jī)是來自 Discord 上 Apache Cassandra 社區(qū)成員的問題。立即加入(Cassandra)戒指團(tuán)契,與社區(qū)成員和專家建立聯(lián)系!

分享到:
標(biāo)簽:聯(lián)網(wǎng)
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定