物聯網數據儲存與分析(上)

MinChe Tsai
SoftChef Blog_CN
Published in
Nov 20, 2020

當物聯網應用陸續完成裝置聯網及雲端架構之後,隨著裝置陸續啟用,數據資料源源不絕地往雲端發送,如何有效率的存放大量的數據資料以及進行資料分析,將會是這篇文章的主要內容。

本篇文章將採用以下的雲端架構圖進行說明,主要將分為數據保存、數據分析及視覺圖表呈現,將分成上下兩篇文章,分別進行實作與細部解說。

數據倉儲與資料分析的雲端架構圖

物聯網裝置數據該如何保存?

基於物聯網適用無伺服器架構的情境下,在AWS雲端服務中,主要針對存取效率、儲存成本、資料維護等方向進行考量,有以下幾種複合選擇:

  1. DynamoDB 使用非關聯式資料庫(Non-SQL)儲存裝置資料是不錯的選擇,在查詢資料時的效率非常快,但隨著資料量日漸增長後,在查詢成本(RCU)上會造成不小的負擔,因此建議規劃為存放熱資料(Hot data)的地方,並且需要定期清理較久的資料(需耗費WCU),適合用於顯示即時資料需求的小型應用場景。
  2. S3(Simple-Storage-Service) 選擇以物件型態(檔案)儲存的方式,看似有點奇怪,但只要搭配ETL(Extract-Transform-Load)的Glue服務,對大量的檔案進行抽取、轉換及載入後,即可將資料轉換為可查詢的資料庫型態,再藉由Athena服務以SQL語法的方式查詢及輸出。S3最大的優勢在於極低的儲存成本,即使資料量不斷增加,只需規畫妥善的儲存路徑即可。在查詢效率方面,雖然難以查詢即時資料,但對大量且複雜的歷史資料查詢時,還是能夠保持相同的速度,意即不會隨著資料增長而增加查詢時間。
  3. S3 Glacier 搭配S3的設定,通常會將超過查詢期限的資料,自動的將其轉換使用Glacier方式進行封存,並依照不同的古老程度設置封存的深度。不同深度的封存影響儲存成本及查詢時間,成本越低查詢越慢,但距今越久遠的資料越不會需要經常查詢,因此十分適合長期的資料保存。
  4. RDS Aurora 雖然Aurora是基於無伺服器架構的關聯式資料庫,並且內建讀寫分離的機制,但是仍然使用傳統的資料庫引擎MySQL或PostgreSQL,若是要用來儲存大量的裝置數據並不是最好的選擇。在查詢效率上,受限於先天關聯式設計特性,需要耗費比非關聯式更多的運算資源進行運算,需要額外費心於資料結構的設計之上。在儲存成本方面,由於資料存放在固定的磁碟叢集之中,需要負擔磁碟容量及讀寫次數的費用,在維運過程中,仍須監控使用容量情況,並自行保持擴充。因此整體來說,Aurora並不適合用來儲存大量的裝置數據。
  5. Redshift 是基於資料倉儲概念而生的資料庫,能夠融合並查詢前面所提到的各種資料庫系統所結合而成的資料湖(Data Lake)。我們能夠將裝置數據保存於S3,同時將清洗過的資料保存於Redshift,最後提供關聯式資料庫的SQL語法進行資料查詢。在查詢效率方面,較小量的數據資料(少於1TB),可以選擇DC2系列的EC2實例,該系列擁有不錯的分析運算能力可以處理數據,僅需支付EC2實例的費用。如果需要針對大量的數據資料(大於1TB以上)進行分析,則可選用RA3系列的EC2實例進行處理,但需要額外負擔數據存儲的費用。接下來的數據分析中,Redshift將扮演非常重要的角色。
  6. Timestream 於近期推出以時間序(Time series)為導向的非關聯式資料庫,是專為物聯網而生的服務,能夠將數據資料區分為最新資料,存放於記憶體中;近期資料,存放於SSD磁碟;長期資料中,存放於磁帶中。不同的時間區間,可依照商業邏輯來定義時間,例如一天、一個月及一年,Timestream將自動的依照數據存放時間,移轉至對應的儲存體之中。值得一提的是,可以設定最久保存時間,超過保存時間的資料將自動消失,以節省儲存費用。在查詢效率上,十分符合物聯網的查詢需求,以時間為導向的數據分析為主,是特別優化的查詢引擎。在儲存成本方面,依照新舊資料分別存放於不同儲存體的特性,只需要合理分配設定,即可最佳化儲存費用。(此篇文章撰寫期間,Timestream仍有許多與分析相關的整合性問題需要完善,因此暫時不列入規劃之中)

大量與即時的數據該如何處理?

當數據經由AWS IoT Core接收之後,經由Rules作為第一次的數據清洗後,即將寫入資料庫,為了降低資料寫入次數所造成的費用,建議使用AWS Kinesis Firehose作為資料串流管道,可將每一筆數據先暫存起來,依照串流的時間或容量設定,當其中一個條件滿足時,才將資料進行交付處理(Delivery)。舉例來說,我們可以將緩衝時間設為每三分鐘,最大緩衝容量為3MB,若當前五分鐘內的資料量已超過3MB時,便會交付資料;反之,固定每三分鐘進行一次交付。

緩衝時間可介於60~900秒,緩衝容量1~128MB https://docs.aws.amazon.com/firehose/latest/dev/create-configure.html

依照架構圖所示,資料將交付至Redshift,按緩存資料逐筆轉換欄位(JSON)存入資料庫之中,並同時備份保存原始資料至S3 Bucket,依照交付時間(年月日時)作為進行資料夾名稱,檔案內容將會是此次緩存的所有資料內容。

在資料交付之前,可以指定一組Lambda函式,將每次緩存的資料交由自訂的程式邏輯進行清洗、運算或整理後,才進行最後的交付。

Amazon Redshift簡介

在開始建立Redshift之前,需要先了解相關名詞及用途。叢集伺服器(Cluster)是最基本的核心功能,需要建立一組(Single Node)或多組(Multiple Nodes)的EC2實例作為運算資源。Redshift必須被分配在私有的子網域之中,僅能透過指定的Security Group供應外部服務(Tableau)連線。

Redshift的詳細雲端架構圖

由於Redshift是由知名的PostgreSQL資料庫引擎作為基礎,進行大量資料運算的引擎優化,並搭配強大的運算能力而形成的全受管服務,在稍後的操作過程中,可以使用相容PostgreSQL的客戶端資料庫軟體或直接在AWS Redshift平台中進行資料庫的各種操作。

實現IoT Core, Data Firehose與Redshift雲端架構部署

在開始建置物聯網雲端架構之前,請先確認具備以下條件:

  1. 一組AWS帳號
  2. AWS CDK運行環境及相關操作知識
  3. 下載本文的範例原始碼,連結至Github

準備就緒後,可以直接執行CDK的部署指令

// 初始化你的CDK環境cdk bootstrap// 開始部署物聯網雲端架構cdk deploy --app='./bin/iot-and-redshift.js'// 完整參數(選填)cdk deploy --app='./bin/iot-and-redshift.js' \
--parameters Database=iot \
--parameters Port=5439 \
--parameters Username=minche \
--parameters Password=Iot#52657055 \
--parameters TableName=temperature

如果你的AWS本地環境配置不是預設的名稱,可以透過--profile="YOUR AWS PROFILE"來變更環境名稱。

在等候部署的期間,可以到AWS CloudFormation Console查看目前的進度,由於部署較為複雜,通常需要5~8分鐘的等待時間。

部署IoT與Redshift雲端資源的過程

此次部署的內容包含以下資源:

  1. 一組S3 Bucket,用於存放原始資料
  2. 一組Redshift的資料庫叢集(Single node),以及相關VPC等配置
  3. 一組Kinesis Data Firehose的交付串流(Deliver stream)
  4. 一組IoT的Thing
  5. 一組IoT的Topic rule,並連接至Firehose

在部署完成後,即可開始讓設備透過MQTT將數據送往雲端進行儲存。

從Outputs中可以取得部署資源的重要資訊

連線到Redshift

要連線到Redshift有許多種方式,以下我們將示範兩種方式:

  1. 使用AWS Redshift Console檢閱資料庫
  2. 使用客戶端軟體檢閱資料庫(使用DBeaver)

在部署完成後,可以在Redshift的Clusters中找到名為tableau-cluster的資源,使用查詢功能並輸入建立時的帳號與密碼,接著就能進行資料庫查詢。

使用AWS Console內建的查詢功能
輸入部署時所指定的資料庫密碼
Redshift的查詢介面

第二種方式,使用客戶端軟體連線至資料庫,這裡使用DBeaver作為示範,可以使用任何相容PostgreSQL的客戶端軟體進行連線。

由於Redshift預設存在於私密的子網域(Private subnet),以確保資料庫不會暴露於公開的網路之中,請參考官方文件進行設定。

新增一組限定IP的Internet gateway,開放連線到私密的子網域

從CloudFormation的Outputs中,可以取得正確連線資訊,在輸入後即可連線至Redshift資料庫。

注意:每次新部署的Host皆不同,會由AWS隨機產生不同的位置

設置正確即可成功連線

建立資料表

在開始將模擬裝置的數據傳送上來之前,我們需要先手動在Redshift資料庫中,建立一張新的資料表。

create table public.temperature
(
thing_name varchar(32),
temperature float,
updated_at timestamp
);

Kinesis Data Firehose的配置

負責將資料交付至Redshift的串流功能

由於Redshift預設存在於私密的子網域(Private subnet),以確保資料庫不會暴露於公開的網路之中,因此我們需要將Firehose的IP位置,手動加入對應Route table的設定之中。

Kinesis Data Firehose的IP位置
將Data Firehose的IP位置授權從公開網路經由Internet Gateway存取Redshift

裝置及數據模擬器

為了方便測試,範例原始碼中包含一組裝置模擬器,將會定時(每3秒)把數據透過MQTT傳送至IoT Core,並依照Topic rule的設置,將數據交付至Data Firehose進行緩存處理。等待每一次的緩存時間(範例為每60秒),可以觀察到資料已經批次交付至S3 Bucket及Redshift之中。可以在Redshift的查詢功能中,使用SQL語法,將已經交付的資料查詢出來。

node devices/temperature.js
查詢temperature資料表
資料顯示來自溫度計的溫度以及量測時間
S3 Bucket中,已完成批次交付的原始資料

到目前爲止,完成從接收數據、數據緩衝以及資料倉儲的雲端架構,接下來就可以進入數據分析的階段,請參閱下集。

--

--

MinChe Tsai
SoftChef Blog_CN

專注於物聯網雲端架構以及各種應用場景, 有任何商業運用想法, 請與我聯絡minche@softchef.com・軟領科技CTO