使用Python進行AWS NoSQL性能實驗室

在多數金融機構中,線上交易處理(OLTP)通常依賴於靜態或不常更新的數據,這類數據又被稱為參考數據。參考數據源並非總是需要ACID交易能力,而是需要支援基於簡單數據存取模式的快速讀取查詢,以及事件驅動架構以確保目標系統保持最新狀態。NoSQL資料庫因此成為滿足這些需求的理想選擇,而AWS等雲端平台則提供了管理完善且高度彈性的數據生態系統

。本文中,我不會斷言哪個AWS NoSQL資料庫更優:所謂更優的資料庫僅存在於特定目的的脈絡中。我將分享一個編碼實驗室,用以評估AWS管理的NoSQL資料庫如DynamoDBCassandraRedisMongoDB的效能

效能測試

I will start by defining the performance test case, which will concurrently insert a JSON payload 200 times and then read it 200 times.

JSON負載

base_db.py中的base/parent類別實現了測試案例邏輯,即執行10個並發線程以建立並讀取200筆記錄。

Python

 

#imports
.....
class BaseDB:

    def __init__(self, file_name='instrument.json', threads=10, records=20):

      ...................................
      
    def execute(self):

        create_threads = []
        for i in range(self.num_threads):
            thread = threading.Thread(
                target=self.create_records, args=(i,))
            create_threads.append(thread)
            thread.start()

        for thread in create_threads:
            thread.join()

        read_threads = []
        for i in range(self.num_threads):
            thread = threading.Thread(target=self.read_records, args=(i,))
            read_threads.append(thread)
            thread.start()

        for thread in read_threads:
            thread.join()

        self.print_stats()

每個執行緒分別在create_recordsread_records中執行寫入/讀取例程。注意,這些函數不包含任何特定於資料庫的邏輯,而是測量每次讀寫執行的性能。

Python

 

def create_records(self, thread_id):

  for i in range(1, self.num_records + 1):
    key = int(thread_id * 100 + i)
    start_time = time.time()
    self.create_record(key)
    end_time = time.time()
    execution_time = end_time - start_time
    self.performance_data[key] = {'Create Time': execution_time}


def read_records(self, thread_id):

  for key in self.performance_data.keys():
    start_time = time.time()
    self.read_record(key)
    end_time = time.time()
    execution_time = end_time - start_time
    self.performance_data[key]['Read Time'] = execution_time

一旦測試案例執行,print_stats函數將打印執行指標,如讀寫平均值和標準偏差(stdev)值,這些指標表明資料庫讀寫性能和一致性(較小的stdev意味著更一致的執行性能)。

Python

 

def print_stats(self):

  if len(self.performance_data) > 0:
    # 從性能數據創建Pandas DataFrame
    df = pd.DataFrame.from_dict(self.performance_data, orient='index')

    if not df.empty:
      df.sort_index(inplace=True)
      # 計算每列的平均值和標準偏差
      create_mean = statistics.mean(df['Create Time'])
      read_mean = statistics.mean(df['Read Time'])
      create_stdev = statistics.stdev(df['Create Time'])
      read_stdev = statistics.stdev(df['Read Time'])

      print("Performance Data:")
      print(df)
      print(f"Create Time mean: {create_mean}, stdev: {create_stdev}")
      print(f"Read Time mean: {read_mean}, stdev: {read_stdev}")

NoSQL代碼

與支持標準SQL的關係型資料庫不同,每個NoSQL資料庫都有自己的SDK。每個NoSQL資料庫的子測試案例類只需實現一個構造器和create_record/read_recod 包含專有資料庫SDK的函數,以幾行程式碼建立資料庫連接並創建/讀取記錄。

DynamoDB測試案例

Python

 

import boto3
from base_db import BaseDB

class DynamoDB (BaseDB):

    def __init__(self, file_name='instrument.json', threads=10, records=20):

        super().__init__(file_name, threads, records)

        dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
        table_name = 'Instruments'
        self.table = dynamodb.Table(table_name)

    def create_record(self, key):

        item = {
            'key': key,
            'data': self.json_data
        }
        self.table.put_item(Item=item)

    def read_record(self, key):

        self.table.get_item(Key={'key': key})


if __name__ == "__main__":

    DynamoDB().execute()

AWS設置

要在AWS帳戶中執行這些性能測試案例,您應遵循以下步驟:

  1. 創建具有訪問所需AWS數據服務權限的EC2 IAM角色。
  2. 啟動EC2實例並分配新創建的IAM角色。
  3. 創建每個NoSQL資料庫實例。

 IAM 角色

DynamoDB 表格

Cassandra 键空间/表格

請注意,DB 主機和憑證在mongo_db.pyredis_db.py模組中已被硬編碼並移除,需要更新為您 AWS 帳戶對應的資料庫連接設定。為了連接到 DynamoDB 和 Cassandra,我選擇使用暫時分配給db_performnace_iam_role IAM 角色的 Boto3 會話憑證。此代碼將在任何 AWS 東部 1 區域帳戶中無需任何修改即可運行。

Python

 

class CassandraDB(BaseDB):

    def __init__(self, file_name='instrument.json', threads=10, records=20):

        super().__init__(file_name=file_name, threads=threads, records=records)

        self.json_data = json.dumps(
            self.json_data, cls=DecimalEncoder).encode()

        # Cassandra 键空间配置
        contact_points = ['cassandra.us-east-1.amazonaws.com']
        keyspace_name = 'db_performance'

        ssl_context = SSLContext(PROTOCOL_TLSv1_2)
        ssl_context.load_verify_locations('sf-class2-root.crt')
        ssl_context.verify_mode = CERT_REQUIRED

        boto_session = boto3.Session(region_name="us-east-1")
        auth_provider = SigV4AuthProvider(session=boto_session)

        cluster = Cluster(contact_points, ssl_context=ssl_context, auth_provider=auth_provider,
                          port=9142)
        self.session = cluster.connect(keyspace=keyspace_name)

連接到 EC2 實例(我使用了 Session Manager),並運行以下 Shell 腳本以執行這些任務:

  1. 安裝 Git。
  2. 安裝 Pythion3。
  3. 克隆 GitHub performance_db 倉庫。
  4. 安裝並激活 Python3 虛擬環境。
  5. 安裝第三方庫/依賴。
  6. 執行每個測試案例。
Shell

 

sudo yum install git
sudo yum install python3

git clone https://github.com/dshilman/db_performance.git
sudo git pull

cd db_performance
python3 -m venv venv
source ./venv/bin/activate

sudo python3 -m pip install -r requirements.txt

cd code
sudo python3 -m dynamo_db
sudo python3 -m cassandra_db
sudo python3 -m redis_db
sudo python3 -m mongo_db

您應該看到前兩個測試案例的以下輸出:

(venv) sh-5.2$ sudo python3 -m dynamo_db

性能數據:

建立時間 讀取時間

1          0.336909   0.031491

2          0.056884   0.053334

3       0.085881   0.031385

4          0.084940   0.050059

5          0.169012   0.050044

..              …        …

916        0.047431   0.041877

917        0.043795   0.024649

918        0.075325   0.035251

919        0.101007   0.068767

920        0.103432   0.037742

 

[200 列 x 2 欄]

建立時間平均值: 0.0858926808834076, 標準差: 0.07714510154026173

讀取時間平均值: 0.04880355834960937, 標準差: 0.028805479258627295

執行時間: 11.499964714050293

(venv) sh-5.2$ sudo python3 -m cassandra_db

效能數據:

    建立時間 讀取時間

1          0.024815   0.005986

2          0.008256   0.006927

3          0.008996   0.009810

4          0.005362   0.005892

5          0.010117   0.010308

..              …        …

916        0.006234   0.008147

917        0.011564   0.004347

918     0.007857      0.008329

919        0.007260   0.007370

920        0.004654   0.006049

 

[200行 x 2列]

創建時間平均值:0.009145524501800537,標準差:0.005201661271831082

讀取時間平均值:0.007248317003250122,標準差:0.003557610695674452

執行時間:1.6279327869415283

測試結果

DynamoDB Cassandra MongoDB Redis
Create mean: 0.0859
stdev: 0.0771
mean: 0.0091
stdev: 0.0052
mean: 0.0292
std: 0.0764
mean: 0.0028
stdev: 0.0049
Read mean:  0.0488
stdev: 0.0288
mean: 0.0072
stdev: 0.0036
mean: 0.0509
std: 0.0027
mean: 0.0012
stdev: 0.0016
Exec Time 11.45 sec 1.6279 sec 10.2608 sec 0.3465 sec

我的觀察

  • I was blown away by Cassandra’s fast performance. Cassandra support for SQL allows rich access pattern queries and AWS Keyspaces offer cross-region replication.
  • I find DynamoDB’s performance disappointing despite the AWS hype about it. You should try to avoid the cross-partition table scan and thus must use an index for each data access pattern. DynamoDB global tables enable cross-region data replication.
  • MongoDB擁有極其簡單的SDK,使用起來充滿樂趣,並且對JSON數據類型提供最佳支持。您可以創建索引並對嵌套的JSON屬性運行複雜查詢。隨著新的二進制數據格式的出現,MongoDB可能會失去其吸引力。
  • Redis的性能驚人地快,然而,歸根結底,即使它支持複雜的數據類型,它仍然是一個鍵/值緩存。Redis提供了強大的功能,如流水線和腳本編寫,通過將代碼傳遞給Redis在服務器端執行,進一步提高查詢性能。

結論

總而言之,選擇AWS管理的NoSQL數據庫作為您的企業參考數據平台,取決於您的具體優先事項。如果性能和跨區域複製是您的首要關注點,AWS Cassandra脫穎而出,成為明顯的贏家。DynamoDB與其他AWS服務如Lambda和Kinesis整合良好,因此對於AWS原生或無服務器架構來說是一個很好的選擇。對於需要強大JSON數據類型支持的應用程序,MongoDB領先。然而,如果您的重點是快速查找或高可用性的會話管理,Redis證明是一個極好的選擇。最終,這一決策應與您組織的獨特需求相一致。

一如往常,您可以在本文早前提及的GitHub倉庫中找到該程式碼(參見上方Shell腳本任務#3)。若在執行此程式碼或設置AWS時遇到困難,歡迎隨時聯繫我尋求協助。

Source:
https://dzone.com/articles/aws-nosql-performance-lab-using-python