在多數金融機構中,線上交易處理(OLTP)通常依賴於靜態或不常更新的數據,這類數據又被稱為參考數據。參考數據源並非總是需要ACID交易能力,而是需要支援基於簡單數據存取模式的快速讀取查詢,以及事件驅動架構以確保目標系統保持最新狀態。NoSQL資料庫因此成為滿足這些需求的理想選擇,而AWS等雲端平台則提供了管理完善且高度彈性的數據生態系統
。本文中,我不會斷言哪個AWS NoSQL資料庫更優:所謂更優的資料庫僅存在於特定目的的脈絡中。我將分享一個編碼實驗室,用以評估AWS管理的NoSQL資料庫如DynamoDB、Cassandra、Redis及MongoDB的效能
。
效能測試
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筆記錄。
#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_records
和read_records
中執行寫入/讀取例程。注意,這些函數不包含任何特定於資料庫的邏輯,而是測量每次讀寫執行的性能。
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
意味著更一致的執行性能)。
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測試案例
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帳戶中執行這些性能測試案例,您應遵循以下步驟:
- 創建具有訪問所需AWS數據服務權限的EC2 IAM角色。
- 啟動EC2實例並分配新創建的IAM角色。
- 創建每個NoSQL資料庫實例。
IAM 角色
DynamoDB 表格
Cassandra 键空间/表格
請注意,DB 主機和憑證在mongo_db.py和redis_db.py模組中已被硬編碼並移除,需要更新為您 AWS 帳戶對應的資料庫連接設定。為了連接到 DynamoDB 和 Cassandra,我選擇使用暫時分配給db_performnace_iam_role
IAM 角色的 Boto3 會話憑證。此代碼將在任何 AWS 東部 1 區域帳戶中無需任何修改即可運行。
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 腳本以執行這些任務:
- 安裝 Git。
- 安裝 Pythion3。
- 克隆 GitHub performance_db 倉庫。
- 安裝並激活 Python3 虛擬環境。
- 安裝第三方庫/依賴。
- 執行每個測試案例。
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