iT邦幫忙

2025 iThome 鐵人賽

DAY 17
0
Build on AWS

AWS架構師的自我修養:30天雲端系統思維實戰指南系列 第 20

Day 11-6 | 資料庫設計哲學:需求解析、技術選型與 Schema 設計策略(六) - 核心設計策略AWS實戰解析:冷熱資料分層 -以TSMC晶圓IoT、LLM Training為例

  • 分享至 

  • xImage
  •  

6. 冷熱資料分層(Data Tiering)

這是一個在大型系統中極其重要,但經常被初學者忽略的策略,它的核心不是技術,而是一種經濟學思維。而且非常容易跟快取設計策略結合與搞混。

我們用一個你我每天都會接觸的例子來理解:衣櫃

想像一下,如果你的衣櫃是一個無限大的、恆溫恆濕、有專人打理的頂級衣帽間,那當然很棒,有收藏的各式各樣包包、恆河沙數的經典設計手錶、不勝凡幾的鞋款,簡單來比喻 - 我們是中東石油大亨,有一整座摩天百貨公司是我們的衣櫃。

但現實是,就算如此我們的居住空間(儲存資源)是有限且昂貴的;更別說,要查找也是需要花費時間成本。

我們不會把十幾年沒穿過的高中制服,和明天要穿的正裝禮服、常穿的 T-shirt 放在衣櫃裡最順手的位置。這不合邏輯,也浪費了寶貴的空間。

冷熱資料分層的核心哲學 ,就是承認 「所有資料都生而 平等」。資料的價值和被存取的頻率會隨著時間流逝而急劇下降。因此,我們應該像整理衣櫃一樣,將資料的儲存成本與其當前的業務價值和存取頻率進行精準匹配

其終極目標不是為了「快」或「大」,而是為了「 省 (Cost-Effective) 」。是在不犧牲必要效能的前提下,以最低的總體成本儲存海量資料。

那我們可能會好奇一個問題,這樣子做分層不就是快取了嗎?

這個問題發現得非常好,這代表我們已經開始考慮這些策略背後的 需求實現共通模式 了。它們看似相似,都提到了「熱」與「冷」,但它們解決的核心問題、出發點和最終目的,是完全不同的。

簡單來說:快取是為了 「快」 ,而冷熱分層是為了 「省」

快取 (Caching) 是一種 「複製」 策略,而 冷熱資料分層 (Data Tiering) 是一種 「搬家」 策略。

讓我們從衣櫃前離開一下,來到放了我最喜歡的百事可樂的冰箱前。

快取策略 (Caching) - 我的冰箱冷藏區

  • 哲學:為了讓我 最快拿到最常吃 的東西。
  • 動作:從超市買回一整箱百事可樂(資料庫),但我不會把整箱都放在廚房檯面上。我會拿一瓶出來,放進冰箱門邊的置物架上( 記憶體快取 / Redis )。這瓶百事可樂是原始百事可樂的 「副本」,目的是為了讓我口渴時能在一秒內拿到。
  • 核心問題:解決 「存取速度」 的問題。
  • 數據本體:冰箱裡的百事可樂喝完了,還要去儲藏室拿新的。原始數據(正本)的位置從未改變。

冷熱資料分層 (Data Tiering) - 我的冰箱 vs. 地下室的冰櫃

  • 哲學:為了用最低的成本儲存所有食物,同時不讓冰箱太擠。
    動作:
  • 熱層:這週要吃的牛排、蔬菜,放在冰箱冷藏區(高效能 SSD / RDS)。
  • 冷層:買來預備一個月後才要吃的冷凍披薩、冰淇淋,我會把它們搬到地下室那個比較耗電、但容量巨大的獨立冰櫃裡(低成本物件儲存 / S3)。
  • 凍結層:去年感恩節吃剩的、可能永遠不會再吃的 "火雞" ,我先用真空袋包好,扔到冰櫃最底層,然後等到哪天想到的時候再到車庫把它銷毀(歸檔儲存 / S3 Glacier)。
  • 核心問題:解決 「儲存成本」 的問題。
  • 數據本體:這是一個 「搬家」 的過程。冷凍披薩的 原始數據(正本),真的從昂貴的「熱層」被移動到了便宜的「冷層」

所以,它們不是一回事。但在一個完整的系統架構中,它們經常協同工作:

我們對 「熱層」 的資料庫(例如 RDS)前面,再加一層 快取(例如 ElastiCache) ,來應對最高的流量洪峰。同時,我們設定一個 冷熱分層 的策略,定期將 RDS 中不常被訪問的舊數據,自動 「搬家」 到 S3,以節省昂貴的 RDS 儲存費用。

接下來讓我們忘了被放在冷凍庫的火雞,轉身回到衣櫃前。

分層的 抽象概念,就是建立一個「智慧管家 (Lifecycle Policy)」,它會根據你設定的規則(例如「這件衣服超過 90 天沒穿了」), 自動地搬移 符合條件的衣服從衣櫃外層移到抽屜,再從抽屜移到床底的箱子裡。

  • 熱資料 (Hot Data):掛在衣櫃最外層、隨手可及的衣服 - 當然,也有可能在床上或是枕頭下。這是最近常穿的、明天可能要穿的。對應到系統中,就是儲存在最昂貴、最快的 記憶體 (In-Memory Cache, Redis) 或 高速 SSD 上的資料,需要毫秒甚至微秒級的存取。

  • 溫資料 (Warm Data):摺好放在衣櫃抽屜裡的衣服。 你不是每天穿,但一週可能穿一次。拿取它們需要「拉開抽屜」這個額外動作。對應到系統中,就是儲存在標準 SSD (如 RDS) 上的資料,需要毫秒級的存取。

  • 冷資料 (Cold Data):裝在箱子裡、放在衣櫃頂部或床下的換季衣物。 你幾個月才會動一次。拿取它們需要搬箱子、打開,比較費時。對應到系統中,就是儲存在廉價的 物件儲存 (如 Amazon S3 Standard) 上的資料,存取延遲可能在數十到數百毫秒。

凍結資料 (Frozen Data):打包好、存放在老家地下室或外部倉庫裡的高中制服、紀念 T-shirt。你幾乎永遠不會再穿,但有情感價值或合規需求(萬一開同學會呢?)。拿取它們需要一個「計畫」,開車過去,花幾個小時才能找到。對應到系統中,就是儲存在 歸檔儲存 (如 Amazon S3 Glacier) 上的資料,存取需要幾分鐘到幾小時。

graph TD
    subgraph "資料生命週期"
        A[熱 (Hot)<br/>記憶體/SSD<br/>常穿的衣服] -->|超過 30 天未存取| B[溫 (Warm)<br/>標準 SSD<br/>抽屜裡的衣服]
        B -->|超過 90 天未存取| C[冷 (Cold)<br/>物件儲存 S3<br/>床底的換季衣物]
        C -->|超過 1 年未存取| D[凍結 (Frozen)<br/>歸檔儲存 Glacier<br/>老家的紀念品]
    end

    subgraph "存取成本與延遲"
        A -- "成本:$$$$<br/>延遲:微秒" --> B
        B -- "成本:$$$<br/>延遲:毫秒" --> C
        C -- "成本:$$<br/>延遲:秒級" --> D
        D -- "成本:$<br/>延遲:分鐘/小時"
    end

既然我們要像管家一樣自動整理資料,就需要遵循幾條關鍵的設計原則:

設計原則:在成本、效能與可用性之間取得平衡

  1. 義清晰的資料生命週期 (Define Clear Lifecycle Policies):
  • 這是策略的基石。你必須能回答:「什麼樣的資料算冷資料?」

  • 原則:策略必須基於客觀且可量化的指標。最常見的就是時間。例如:

    • 交易訂單在「完成」狀態 30 天後,從 RDS (溫) 遷移到 S3 (冷)。
    • 用戶日誌在 90 天後,從 S3 Standard (冷) 遷移到 S3 Glacier (凍結)。
    • 7 年後,從 Glacier 中徹底刪除以符合 GDPR 法規。 2.確保存取的透明性 (Ensure Transparent Access):
  • 你的應用程式不應該為了拿一件存在地下室的衣服,而需要一套完全不同的複雜邏輯。

  • 原則:系統應該提供一個統一的資料存取視圖。當應用程式請求一筆 5 年前的訂單時,資料層應該能自動地從 Glacier 中提取資料,而不是直接告訴應用程式「找不到」。這可能意味著 API 需要支援非同步回應模式,即「您的請求已收到,資料準備好後會通知您」。

  1. 自動化遷移過程 (Automate Data Movement):
  • 你不會想每個月手動把上萬件衣服從衣櫃搬到地下室。
  • 原則:資料在不同層級之間的移動必須是自動化、可靠且可監控的。這通常通過排程作業(Scheduled Jobs)或雲端服務內建的生命週期規則(如 S3 Lifecycle Policies)來實現。你必須確保遷移過程中資料不會遺失,並記錄下每一次遷移的日誌以供審計。
  1. 權衡檢索成本與時間 (Balance Retrieval Cost and Time):
  • 把所有東西都存到最便宜的「凍結層」聽起來很誘人,但這是一個陷阱。
  • 原則:必須考慮到**「取回資料的成本」**。從 Glacier 中緊急取回大量資料的費用可能非常高昂。在設計時,必須與業務方確認:對於冷資料和凍結資料,他們能接受的最長等待時間和最高檢索預算是多少?這決定了你應該選擇 S3 IA(立即存取但稍貴)還是 S3 Glacier(等待幾分鐘但極便宜)。

抽象分層概念

  • 熱資料(Hot)

    • 記憶體資料庫(Redis/Hazelcast)
    • 高速 SSD
    • 微秒級存取需求
  • 溫資料(Warm)

    • 傳統 SSD
    • 關聯式資料庫
    • 毫秒級存取需求
  • 冷資料(Cold)

    • 機械硬碟
    • 物件儲存(S3)
    • 秒級存取需求
  • 凍結資料(Frozen)

    • 磁帶儲存
    • 歸檔系統
    • 分鐘級存取需求

常見應用場景 :

  • 幾乎所有大型系統都會遇到,如果沒有,那就該換我們跑了

以下我們來看看一些完整體現冷熱分層威力的 「情境題」

AWS 實現 1:IoT TSMC 晶圓工廠的數據生命週期

想像一下我們是 TSMC 台積電的系統架構師,要負責處理一個遍布數千個感測器的晶圓、晶片工廠,這些感測器以毫秒等級的串流回報溫度、壓力、震動頻率等數據。這些數據的價值是以秒為單位在逐步衰退的。

  • 核心需求哲學:即時數據用於 立即反應 (Immediately React),歷史數據用於 學習 (Learn)

  • 抽象概念:數據從 「即時警報」的價值 => 衰退為「趨勢分析」的價值 => 最終變為「模型訓練」的價值

  • 熱層 (Hot Tier):最近 1 小時的原始數據。

    • 業務需求:即時儀表板、異常偵測(如溫度超標)、觸發警報。
    • 儲存:Amazon Timestream 的 記憶體儲存 (In-Memory Store)。專為時間序列數據的超高速寫入和查詢而設計。
  • 溫層 (Warm Tier):最近 24 小時 的聚合數據(例如,每分鐘的平均溫度)。

    • 業務需求:生成每日/每週的效能報告,分析短期趨勢。
    • 儲存:Amazon Timestream 的 磁碟儲存 (Magnetic Store)。Timestream 會自動將舊的原始數據降級到成本更低的磁碟層,並支援對其進行查詢。
  • 冷層 (Cold Tier):超過 3 天的原始數據。

    • 業務需求:用於訓練機器學習模型、預測性維護分析。
    • 儲存:Amazon S3。Timestream 可以配置規則,自動將最舊的數據匯出到 S3 Data Lake 中。
  • 凍結層 (Frozen Tier):超過 365 天的業務化資訊。

    • 業務需求:用於製成模型訓練紀錄、數據使用人員 Log 紀錄...等。
    • 儲存:Deep Archive。Timestream 可以配置規則,自動將最舊的數據封存。
graph TD
    subgraph "數據產生層 (毫秒級)"
        A[🏭 智慧工廠感測器] --> B[AWS IoT Core<br/>(MQTT 協議接入)]
    end

    subgraph "熱層 (Hot Tier) - 即時反應 (秒/分鐘)"
        B --> C[AWS IoT Rules Engine]
        C -->|即時警報| D[Amazon SNS<br/>發送警報給維運人員]
        C -->|寫入時序數據庫| E[Amazon Timestream<br/>(In-Memory Store)]
        E --> F[Grafana / QuickSight<br/>即時監控儀表板]
    end

    subgraph "溫層 (Warm Tier) - 短期分析 (小時/天)"
        E -- 自動降級 --> G[Amazon Timestream<br/>(Magnetic Store)]
        G --> H[生成每日/每週報告<br/>(Lambda + QuickSight)]
    end

    subgraph "冷層 (Cold Tier) - 長期分析 (月/年)"
        G -- 自動匯出 --> I[Amazon S3 Data Lake<br/>(Parquet 格式)]
        I --> J[Amazon Athena<br/>(Ad-hoc SQL 查詢)]
        J --> K[BI 工具<br/>(Tableau, PowerBI)]
    end

    subgraph "凍結層 (Frozen Tier) - 模型訓練 (全部歷史)"
        I -- S3 生命週期規則 --> L[Amazon S3 Glacier Deep Archive]
        L -- 按需恢復 --> M[Amazon SageMaker<br/>(訓練預測性維護模型)]
    end

    %% 樣式定義
    classDef hot fill:#fce4ec,stroke:#c2185b
    classDef warm fill:#fff9c4,stroke:#fbc02d
    classDef cold fill:#e3f2fd,stroke:#1976d2
    classDef frozen fill:#eceff1,stroke:#546e7a

    class D,E,F hot
    class G,H warm
    class I,J,K cold
    class L,M frozen

Fake Code 實現:Timestream 與 S3 的生命週期管理

import boto3
import time

class SmartFactoryDataTiering:
    def __init__(self, database_name='SmartFactoryDB', table_name='SensorData'):
        self.timestream = boto3.client('timestream-write')
        self.s3 = boto3.client('s3')
        self.db_name = database_name
        self.table_name = table_name

    def setup_timestream_retention(self):
        """
        設定 Timestream 的內存與磁盤保留策略
        熱層 -> 溫層
        """
        try:
            self.timestream.update_table(
                DatabaseName=self.db_name,
                TableName=self.table_name,
                RetentionProperties={
                    'MemoryStoreRetentionPeriodInHours': 24,  # 熱層: 數據在內存中保留 24 小時
                    'MagneticStoreRetentionPeriodInDays': 90 # 溫層: 數據在磁盤中保留 90 天
                }
            )
            print("Timestream retention policy (Hot -> Warm) updated.")
        except Exception as e:
            print(f"Error updating Timestream policy: {e}")

    def setup_s3_lifecycle_policy(self, bucket_name):
        """
        設定 S3 的生命週期策略
        冷層 -> 凍結層
        """
        lifecycle_policy = {
            'Rules': [
                {
                    'ID': 'MoveToGlacierAfter90Days',
                    'Status': 'Enabled',
                    'Filter': {'Prefix': 'sensor-data-archive/'},
                    'Transitions': [
                        {
                            'Days': 90, # 冷層: 數據在 S3 Standard 中保留 90 天
                            'StorageClass': 'GLACIER'
                        }
                    ]
                },
                {
                    'ID': 'MoveToDeepArchiveAfter1Year',
                    'Status': 'Enabled',
                    'Filter': {'Prefix': 'sensor-data-archive/'},
                    'Transitions': [
                        {
                            'Days': 365, # 凍結層: 1 年後移至 Deep Archive
                            'StorageClass': 'DEEP_ARCHIVE'
                        }
                    ]
                },
                {
                    'ID': 'ExpireAfter7Years',
                    'Status': 'Enabled',
                    'Filter': {'Prefix': 'sensor-data-archive/'},
                    'Expiration': {
                        'Days': 2555 # 7 年後刪除以符合合規
                    }
                }
            ]
        }
        try:
            self.s3.put_bucket_lifecycle_configuration(
                Bucket=bucket_name,
                LifecycleConfiguration=lifecycle_policy
            )
            print(f"S3 lifecycle policy (Cold -> Frozen) for bucket '{bucket_name}' updated.")
        except Exception as e:
            print(f"Error updating S3 policy: {e}")

# 使用範例
# manager = SmartFactoryDataTiering()
# manager.setup_timestream_retention()
# manager.setup_s3_lifecycle_policy('my-iot-data-lake-bucket')

AWS 實現 2:AI ML/LLM 資料分層架構設計

在機器學習工作流程中與生成式 AI 代理(AI Agent)的訓練中,數據的價值與其在「模型生命週期」中的階段緊密相關,從資料準備到模型部署,整個流程都適用於分層思想。

  • 核心哲學:為流程的每個階段: 探索 => 訓練 => 推論 => 歸檔 ,提供成本效益最佳的儲存。

  • 抽象概念:數據從「原始素材」轉化為「精煉特徵」,再到「模型成品」,最後成為「歷史檔案」。

  • 熱層 (Hot Tier):當前正在用於訓練的特徵數據集 (Feature Store)。

    • 業務需求:模型訓練和即時推論 (Inference) 需要以極低延遲獲取特徵。
    • 儲存:Amazon SageMaker Feature Store (底層可能是 DynamoDB 或 S3,但有高效能 API)。
  • 冷層 (Cold Tier):原始數據集、實驗記錄、歷史訓練數據。

    • 業務需求:數據科學家需要探索和準備新的訓練集。
    • 儲存:Amazon S3。這是所有原始數據和中間產物最理想的儲存位置。
  • 凍結層 (Frozen Tier):舊版本的模型成品和訓練日誌。

    • 業務需求:為了模型的可重現性和合規審計,需要長期存檔所有訓練過的模型及其相關元數據。
    • 儲存:Amazon S3 Glacier。
graph TD
    subgraph "數據湖 (Data Lake) - 原始素材"
        A[各種業務數據源<br/>(RDS, S3, On-premise)] --> B[AWS Glue<br/>(ETL 任務)]
        B --> C[🧊 冷層/凍結層<br/><b>Amazon S3</b><br/>(原始數據與歷史數據)]
    end

    subgraph "特徵工程 (Feature Engineering)"
        C -- 數據科學家探索 --> D[Amazon SageMaker Studio<br/>(Jupyter Notebook)]
        D --> E[🔥 熱層<br/><b>Amazon SageMaker Feature Store</b><br/>(線上/離線特徵)]
    end

    subgraph "模型訓練 (Model Training)"
        E -- 離線特徵 --> F[SageMaker Training Job]
        F --> G[🧊 冷層<br/><b>Amazon S3</b><br/>(模型成品 .tar.gz)]
        G --> H[SageMaker Model Registry<br/>(模型版本與元數據)]
    end

    subgraph "模型推論 (Model Inference)"
        I[用戶請求] --> J[SageMaker Endpoint<br/>(即時推論)]
        J -- 線上特徵查詢 --> E
        J --> K[返回預測結果]
    end

    subgraph "模型監控與歸檔"
        H -- 舊版本模型 --> L[🧊 凍結層<br/><b>S3 Glacier Deep Archive</b><br/>(模型歸檔以供審計)]
        J -- 捕獲推論數據 --> M[🧊 冷層<br/><b>Amazon S3</b><br/>(用於模型漂移檢測)]
    end

    %% 樣式定義
    classDef hot fill:#fce4ec,stroke:#c2185b
    classDef cold fill:#e3f2fd,stroke:#1976d2
    classDef frozen fill:#eceff1,stroke:#546e7a

    class E hot
    class C,G,M cold
    class L frozen

Fake Code 實現:SageMaker Feature Store 與 S3 的協作

import boto3
from sagemaker.feature_store.feature_group import FeatureGroup

class MLOpsDataTiering:
    def __init__(self, sagemaker_session):
        self.sagemaker_session = sagemaker_session
        self.s3 = boto3.client('s3')

    def create_feature_store(self, feature_group_name, s3_uri):
        """
        創建特徵組,將 S3 中的冷數據轉化為熱數據
        冷層 -> 熱層
        """
        feature_group = FeatureGroup(
            name=feature_group_name,
            sagemaker_session=self.sagemaker_session
        )

        # ... (定義特徵)

        feature_group.create(
            s3_uri=s3_uri, # S3 URI for offline store (冷層備份)
            online_store_config=True, # Enable online store for low-latency access (熱層)
            # ...
        )
        print(f"Feature Group '{feature_group_name}' created. Data is now in Hot Tier.")
        return feature_group

    def archive_old_models(self, model_registry_name, bucket_name):
        """
        將舊版本的模型從 S3 冷層歸檔到凍結層
        冷層 -> 凍結層
        """
        sagemaker = boto3.client('sagemaker')
        paginator = sagemaker.get_paginator('list_model_packages')

        for page in paginator.paginate(ModelPackageGroupName=model_registry_name):
            for model_package in page['ModelPackageSummaryList']:
                # 假設我們歸檔一年前且非 Approved 狀態的模型
                one_year_ago = datetime.now() - timedelta(days=365)
                if model_package['CreationTime'] < one_year_ago and model_package['ModelApprovalStatus'] != 'Approved':

                    model_s3_uri = model_package['InferenceSpecification']['Containers'][0]['ModelDataUrl']
                    s3_key = model_s3_uri.replace(f"s3://{bucket_name}/", "")

                    print(f"Archiving model: {s3_key} to Glacier Deep Archive...")

                    # 複製到一個有生命週期規則的前綴下
                    archive_key = f"model-archive/{s3_key}"
                    self.s3.copy_object(
                        Bucket=bucket_name,
                        CopySource={'Bucket': bucket_name, 'Key': s3_key},
                        Key=archive_key,
                        StorageClass='DEEP_ARCHIVE' # 直接指定儲存等級
                    )

                    # 可以在這裡刪除原始 S3 物件以節省成本
                    # self.s3.delete_object(Bucket=bucket_name, Key=s3_key)

# 使用範例
# ml_tiering = MLOpsDataTiering(sagemaker_session)
# # 將 S3 中的數據加載到熱層
# ml_tiering.create_feature_store('user-activity-features', 's3://my-data-lake/processed/user-activity/')
# # 歸檔舊模型
# ml_tiering.archive_old_models('my-recommendation-model-group', 'my-ml-models-bucket')

在這兩個場景中,冷熱分層都不是一個孤立的策略,而是深度嵌入在整個業務流程中的一種成本與效能的動態平衡藝術。

IoT,分層的依據是時間的衰減 v.s  ML,分層的依據是流程的階段。

總結來說,只要系統中存在 「數據價值隨時間衰減」 的現象,並且 「儲存成本」 是一個需要考慮的因素(事實上,always and almost),那麼冷熱資料分層就是一個必須納入設計工具箱的 trade-off 策略。


上一篇
Day 11-5 | 資料庫設計哲學:需求解析、技術選型與 Schema 設計策略(五) - 核心設計策略AWS實戰解析:分片策略-以新加坡交易華爾街為例
下一篇
Day 11-7 | 資料庫設計哲學:需求解析、技術選型與 Schema 設計策略(七) - 核心設計策略AWS實戰解析:微服務資料庫模式
系列文
AWS架構師的自我修養:30天雲端系統思維實戰指南28
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言