ברוב החברות הפיננסיות, עיבוד עסקאות מקוון (OLTP) בדרך כלל מסתמך על נתונים סטטיים או שמעולם לא מתעדכנים, המכונים גם נתוני עזר. מקורות הנתונים האלה אינם תמיד דורשים יכולות עסקאות ACID, אלא צריכים תמיכה בשאילתות קריאה מהירות המבוססות לרוב על דפוסי גישה פשוטים לנתונים, וארכיטקטורת מובילה לגירוי כדי להבטיח שהמערכות המטרה יישארו מעודכנות. מסדי נתונים NoSQL מתגלים כמועמדים מושלמים לעמוד בדרישות אלה, ופלטפורמות ענן כמו AWS מציעות סביבות נתונים מנוהלות ובעלות עמידות גבוהה.
במאמר זה, אני לא הולך לקבוע איזה מסד נתונים NoSQL של AWS הוא טוב יותר: המושג של מסד נתונים טוב יותר קיים רק בהקשר מסוים. אני אשתף באופן מעשי קוד למדידת ביצועים של מסדי נתונים NoSQL מנוהלים של AWS כגון 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
/parent
בbase_db.py מיישמת את הלוגיקה של המקרה המבוקש של ביצוע 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:
# יצירת מסד נתונים פנדאס מנתוני הביצועים
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, עליכם לעקוב אחר השלבים הבאים:
- יצירת תפקיד IAM עבור EC2 עם הרשאות לגשת לשירותי נתוני AWS הנדרשים.
- פתיחת מופע EC2 והקצאת התפקיד החדש שנוצר.
- יצירת מופע מסד נתונים NoSQL בודד.
תפקיד IAM
שולחן DynamoDB
מרחב מפתח Cassandra / שולחן
אנא שימו לב שהתאריך והמredentials של הDB הוקודדו והוסרו במודולים mongo_db.py ו-redis_db.py ויהיה עליכם לעדכן אותם עם ההתקן המתאים לחיבור למסד הנתונים של חשבון AWS שלכם. כדי להתחבר ל-DynamoDB ו-Cassandra, בחרתי להשתמש במredentials של סשן Boto3 המוקצה זמנית לתפקיד IAM db_performnace_iam_role
. קוד זה ירוץ בכל חשבון AWS באזור East 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 (השתמשתי במכשיר מנהל הסשן), והפעלו את התוכנית השפריצית הבאה כדי לבצע את המשימות הבאות:
- התקן את 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 לביצוע בצד השרת.
מסקנה
לסיכום, בחירת מסד הנתונים הלא-SQL הניהולי על ידי AWS עבור ממשק המידע הארגוני שלך תלויה בעדיפויות הספציפיות שלך. אם ביצועים ושכפול בין אזורים הם הדאגה העיקרית שלך, AWS Cassandra בולט כמנצח ברור. DynamoDB משתלב היטב עם שירותי AWS אחרים כמו Lambda ו-Kinesis ולכן הוא אפשרות מצוינת עבור ארכיטקטורת מקורית של AWS או ללא שרת. עבור יישומים הדרושים תמיכה חזקה בסוגי נתונים JSON, MongoDB מקדים. אם המיקוד שלך הוא על חיפוש מהיר או ניהול של משחקים עבור נכונות גבוהה, Redis מוכיח כאפשרות מצוינת. סופו של דבר, ההחלטה צריכה להתאים לדרישות הייחודיות של הארגון שלך.
כרגיל, תוכלו למצוא את הקוד במאגר GitHub המקושר קודם לכן במאמר זה (ראה משימת תסריט השלד #3 לעיל). אל תהססו ליצור קשר אם אתם זקוקים לעזרה בהפעלת הקוד או בהקמה של AWS.
Source:
https://dzone.com/articles/aws-nosql-performance-lab-using-python