Bij de meeste financiële bedrijven steunt online transactieverwerking (OLTP) zich vaak op statische of zelden bijgewerkte gegevens, ook wel referentiegegevens genoemd. Bronnen van referentiegegevens hebben niet altijd ACID-transactiemogelijkheden nodig, maar hebben eerder ondersteuning voor snelle leesquery’s vaak gebaseerd op eenvoudige gegevenstoegangspatronen, en een gebeurtenisgestuurde architectuur om ervoor te zorgen dat de doelsystemen up-to-date blijven. NoSQL-databases komen als uitstekende kandidaten naar voren om aan deze eisen te voldoen, en cloudplatforms zoals AWS bieden beheerde en zeer robuuste data-ecosystemen.
In dit artikel ga ik niet bepalen welke AWS NoSQL-database beter is: het concept van een betere database bestaat alleen binnen een specifiek doelgericht kader. Ik zal een codelaboraat delen om de prestaties van door AWS beheerde NoSQL-databases zoals DynamoDB, Cassandra, Redis, en MongoDB te meten.
Prestatietesten
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-bericht
De base
/parent
klasse in base_db.py implementeert de testcase-logica van het uitvoeren van 10 gelijktijdige threads om 200 records aan te maken en te lezen.
#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()
Elk thread voert de write/read routine uit in de create_records
en read_records
, respectievelijk. Merk op dat deze functies geen database-specifieke logica bevatten, maar eerder, de prestaties van elke read-and-write uitvoering meten.
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
Zodra de testcase wordt uitgevoerd, drukt de print_stats
functie de uitvoeringsmetrieken af, zoals de read/write gemiddelde en de standaarddeviatie (stdev
) waarden, die de database read/write prestaties en consistentie aangeven (kleinere stdev
impliceert meer consistente uitvoeringsprestaties).
def print_stats(self):
if len(self.performance_data) > 0:
# Maak een Pandas DataFrame van prestatiegegevens
df = pd.DataFrame.from_dict(self.performance_data, orient='index')
if not df.empty:
df.sort_index(inplace=True)
# Bereken gemiddelde en standaarddeviatie voor elke kolom
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 Code
In tegenstelling tot relationele databases die standaard SQL ondersteunen, heeft elke NoSQL-database zijn eigen SDK. De kind-testcaseklassen voor elke NoSQL-database hoeven alleen een constructor en create_record/read_recod
functies te implementeren die de propriëtaire database SDK bevatten om een databaseverbinding te instantiëren en om records te creëren/lezen in een paar regels code.
DynamoDB Test Case
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 Setup
Om deze prestatietestcases uit te voeren in een AWS-account, moet u de volgende stappen volgen:
- Maak een EC2 IAM-rol met bevoegdheden om de vereiste AWS-gegevensdiensten te benaderen.
- Start een EC2-instantie en wijs de zojuist gemaakte IAM-rol toe.
- Creëer elke NoSQL-database-instantie.
IAM Rol
DynamoDB Tabel
Cassandra Keyspace/Tabel
Let op dat de DB host en referenties hardcoded waren en verwijderd zijn in de mongo_db.py en redis_db.py modules en zullen moeten worden bijgewerkt met de corresponderende databaseverbinding instellingen voor uw AWS-account. Om verbinding te maken met DynamoDB en Cassandra, koos ik ervoor om de tijdelijk toegewezen Boto3-sessiereferenties te gebruiken voor de db_performnace_iam_role
IAM Rol. Deze code zal in elke AWS-account in de regio East 1 zonder enige aanpassing kunnen worden uitgevoerd.
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()
# Configuratie van Cassandra Keyspaces
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)
Verbind met de EC2-instantie (ik gebruikte de Session Manager) en voer de volgende Shell-script uit om deze taken uit te voeren:
- Installeer Git.
- Installeer Pythion3.
- Kloon de GitHub performance_db repository.
- Installeer en activeer de Python3 virtuele omgeving.
- Installeer externe bibliotheken/afhankelijkheden.
- Voer elke testcase uit.
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
U zou het volgende resultaat voor de eerste twee testcases moeten zien:
(venv) sh-5.2$ sudo python3 -m dynamo_db Prestatiegegevens: Create Time Read Time 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 rijen x 2 kolommen] Gemiddelde Create Time: 0.0858926808834076, standaarddeviatie: 0.07714510154026173 Gemiddelde Read Time: 0.04880355834960937, standaarddeviatie: 0.028805479258627295 Uitvoeringstijd: 11.499964714050293 |
(venv) sh-5.2$ sudo python3 -m cassandra_db Prestatiegegevens: Create Time Read Time 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 rijen x 2 kolommen] Gemiddelde Create Time: 0.009145524501800537, standaarddeviatie: 0.005201661271831082 Gemiddelde Read Time: 0.007248317003250122, standaarddeviatie: 0.003557610695674452 Uitvoeringstijd: 1.6279327869415283 |
Testresultaten
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 |
Mijn observaties
- 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 heeft een zeer eenvoudige SDK, is leuk om te gebruiken en heeft het beste ondersteuning voor de JSON-gegevenstype. U kunt indexen maken en complexe query’s uitvoeren op geneste JSON-attributen. Als nieuwe binaire gegevensindelingen opkomen, kan MongoDB zijn aantrekkingskracht verliezen.
- Redis prestaties zijn verbazingwekkend snel, echter, aan het eind van de dag is het een sleutel/waardecache, zelfs als het complexe gegevenstypen ondersteunt. Redis biedt krachtige functies zoals pipelining en scripting om de queryprestaties verder te verbeteren door code naar Redis te sturen om op de serverzijde uit te voeren.
Conclusie
Concluderend, het kiezen van de AWS-beheerde NoSQL-database voor uw bedrijfsreferentiegegevensplatform hangt af van uw specifieke prioriteiten. Als prestaties en cross-regio replicatie uw belangrijkste zorg zijn, staat AWS Cassandra als duidelijke winnaar uit de bus. DynamoDB integreert goed met andere AWS-services zoals Lambda en Kinesis en is daarom een geweldige optie voor AWS-native of serverloze architectuur. Voor toepassingen die een uitgebreid ondersteuning vereisen voor JSON-gegevenstypen, neemt MongoDB de leiding. Echter, als uw focus ligt op snelle opzoeking of sessiebeheer voor hoge beschikbaarheid, blijkt Redis een uitstekende optie te zijn. Uiteindelijk moet de beslissing aansluiten bij de unieke eisen van uw organisatie.
Zoals altijd, kun je de code vinden in de GitHub-repo die eerder in dit artikel is gelinkt (zie Shell script taak #3 hierboven). Aarzel niet om contact met mij op te nemen als je hulp nodig hebt bij het uitvoeren van deze code of met de AWS-setup.
Source:
https://dzone.com/articles/aws-nosql-performance-lab-using-python