Aerospike의 서열화 또는 압축 대상은?곰곰이 생각하다.
데이터를 백엔드 데이터베이스에 저장하기 전에 클라이언트가 데이터를 서열화하고 압축하는 것은 흔히 볼 수 있는 모델이다.Aerospike 고객과 협력할 때 자주 이런 상황을 만났는데 보통 프로토콜 버퍼(protobuf)나 Gzip JSON 형식으로 나타난다.결국 네트워크 대역폭과 스토리지를 줄이려는 사람은 누구입니까?
단, 예를 들어 간단한 수령/출력 캐시가 아니라면, 당신은 아주 적은 수익을 위해 강력한 Aerospike 기능을 희생할 수 있습니다 - 있으면
클라이언트에서 객체를 시리얼화하고 압축하면 다음과 같은 이점이 있습니다.
또한 Aerospike는 응용 프로그램에서 어떠한 추가 작업도 하지 않고 합리적인 논리와 유연성을 증가시킬 것이다.
이것들은 모두 매우 유용한 기능들이다 - 특히 CDT 업무는어리석은 get/put 캐시만 원한다는 것을 알지 않으면 놓치고 싶지 않다.
하지만 넌 극객이야...나는 극객이다...이 점을 quick'n dirty Python으로 살펴봅시다.
시리얼화/압축 물방울 vs Aerospike CDT 성능
예를 들어 하나의 용례를 가정하면 그것은 날짜에 따라 모든 구매 거래를 정리하고 복합 키(예를 들어
monthly:<YYYYMM>:<Account ID>
)를 사용하여 그것들을 달과 계정에 따라 구분된 기록에 저장한다.Python에서 각 레코드는 중첩된 목록과 사전이 있는 표준 사전으로 나타날 수 있습니다.
'monthly:201901:00001' {
'acct': '00001',
'loc': 1,
'txns': {
'20190101': [
{
'txn': 1,
'ts': 50607338,
'sku': 5631,
'cid': "GFOBVQPRCZVT",
'amt': 873300,
'qty': 23,
'code': 'USD'
},
{ ... }
]
'20190102': [ ... ]
}
}
txns
키는 사전을 포함하는데, 이 사전의 키마다 YYMMDD
형식의 한 달 중 하루이며, 이 값은 해당 일의 업무 목록입니다.클라이언트를 서열화/압축하는 것과 Aerospike 내장 기능을 사용하는 장점과 단점을 강조하기 위해 두 개의 Aerospike 이름 공간을 설정하였다.
첫 번째 명칭 공간
ns1
은 압축을 사용하지 않은 파일 저장 엔진을 사용합니다.기록을 BLOB로 저장하는 데 사용됩니다. 이 BLOB는 JSON으로 서열화되었고, Python 코드에서 zlib 레벨 6 (기본값) 을 사용하여 압축됩니다.namespace
파일의 aerospike.conf
섹션은 다음과 같습니다.namespace ns1 {
replication-factor 1
memory-size 2G
storage-engine device {
file /opt/aerospike/data/ns1.dat
filesize 100M
}
}
두 번째 이름 공간 ns2
은 ZStandard compression level 1(압축량이 가장 작고 성능이 가장 우수)의 파일 저장 엔진을 사용합니다.레코드를 Aerospike CDT로 저장하는 데 사용됩니다.namespace
파일의 aerospike.conf
섹션은 다음과 같습니다.namespace ns2 {
replication-factor 1
memory-size 2G
storage-engine device {
file /opt/aerospike/data/ns2.dat
filesize 100M
compression zstd
compression-level 1
}
}
generate-data.py
이라는 파이톤 스크립트를 사용하여 상기 데이터 모델로 가상 데이터를 생성하여 두 개의 이름 공간에 불러옵니다.그것은 10개의 계좌를 위해 2년간의 역사 거래 데이터를 생성하고 계좌마다 매일 250건의 거래를 한다.generate-data.py
에서 두 개의 명칭 공간에 데이터를 불러오는 부분을 살펴보자.'blob'버전은 먼저 파이톤의 대상을 JSON으로 변환한 다음,zlib을 사용하여 JSON 문자열을 압축한 다음, 기록을 ns1
의 명칭 공간에 쓴다.'cdt' 버전은 파이톤 대상을 ns2
이름 공간에 그대로 기록할 뿐입니다.# write each record
start = time()
for pk, record in objects.items():
if object_type == 'blob':
record_data = {'object': zlib.compress(json.dumps(record).encode("utf-8"), zlib_level)}
elif object_type == 'cdt':
record_data = record
key = (namespace, set_name, pk)
client.put(key, record_data,
policy={'exists': aerospike.POLICY_EXISTS_CREATE_OR_REPLACE}
)
elapsed = time() - start
generate-data.py
은 각 Aerospike 이름 공간에 가상 객체를 로드하면 해당 이름 공간에 대한 통계를 출력합니다.$ python3 generate-data.py
Aerospike: 127.0.0.1:3000 ns1.example
Run time: 9.354 seconds
Object type: blob
Object count: 240
Avg object size: 217.0 KiB
Compression ratio: -
---
Aerospike: 127.0.0.1:3000 ns2.example
Run time: 5.610 seconds
Object type: cdt
Object count: 240
Avg object size: 182.5 KiB
Compression ratio: 0.349
---
따라서 Aerospike 원본 CDT를 사용하고 압축 기능을 사용하면 더 작은 대상(더 좋은 저장 압축)을 생성하고 데이터를 더 빨리 불러올 수 있다는 것이 분명하다.그 중 일부 원인은 다음과 같다. (a) Aerospike가 데이터를 압축할 때 ZStandard compression을 사용하는 것이지 Python 코드에서 사용하는 zlib을 사용하는 것이 아니다. (b) Aerospike는 매우 빠르고 정적 형식의 컴파일러 언어(C lang)로 구축된 것이고 우리의 Python 코드는 해석기에서 실행되는 비교적 느리고 동적 유형의 언어이다.그러니까 이거 사과 아니야, 사과.
그러나 응용 프로그램 개발의 측면에서 볼 때, 이곳의 두 가지 관건적인 요점은Aerospike 압축은 기본적으로 무료이며, 사용자가 사용하는 것은 모국어 유형이다.
용례: 백그라운드 읽기/쓰기 스캔을 통해 데이터를 수정합니다
클라이언트를 서열화/압축할 때 사용할 수 없는 고급 Aerospike 기능을 활용할 수 있는 가치를 설명하기 위해 데이터 교정 용례를 살펴보겠습니다.응용 프로그램에 오류가 있다고 가정하면 계정 하나(
loc
)의 위치(acct
) 값이 정확하지 않습니다.클라이언트에 기록이 서열화되고 압축되면, 프로그램 코드는 네트워크를 통해 모든 기록을 프로그램 RAM으로 읽고, 이를 반서열화하고, 압축을 풀고, 수정한 다음, 네트워크를 통해 전체 기록을 다시 써야 한다.
그러나 서버측 압축이 있는 Aerospike CDT를 사용하면 background read/write scan이 있는 predicate filter을 시작하여 Aerospike 노드에서 작업을 완전히 끝낼 수 있다.
Python 스크립트
correct-data.py
에서 설명합니다.이 스크립트는 위의 generate-data.py
에서 생성한 것과 같은 데이터를 조작합니다.우선 술어 필터를 설정합니다. 이 필터는 계정 ID(
acct
)가 00007
이고 현재 위치 ID(loc
)가 5
인 기록만 필터합니다.account_to_correct = '00007'
incorrect_location = 5
predicate_expressions = [
# push expressions to filter by loc=5
predexp.integer_bin('loc'),
predexp.integer_value(incorrect_location),
predexp.integer_equal(),
# push expression to filter by acct=00007
predexp.string_bin('acct'),
predexp.string_value(account_to_correct),
predexp.string_equal(),
# filter by the `loc` AND `acct` expressions
predexp.predexp_and(2)
]
policy = {
'predexp': predicate_expressions
}
다음에 상기 술어 표현식을 사용하여 모든 Aerospike 노드에 배경 스캔을 보내서 스캔 결과를 필터하고 모든 결과를 기록할 수 있도록 일련의 쓰기 작업을 전달합니다.이 경우 쓰기 작업에는 위치 ID(loc
)를 2
으로 업데이트하는 작업만 포함됩니다.correct_location = 2
# Do a background scan, which runs server-side, to update the records that
# match the predicate expression with the correct value for 'loc'.
ops = [
operations.write('loc', correct_location)
]
bgscan = client.scan(namespace, set_name)
bgscan.add_ops(ops)
scan_id = bgscan.execute_background(policy)
print("Running background read/write scan. ID: {}".format(scan_id))
# Wait for the background scan to complete.
while True:
response = client.job_info(scan_id, aerospike.JOB_SCAN)
if response["status"] != aerospike.JOB_STATUS_INPROGRESS:
break
sleep(0.25)
저것은 무엇입니까?당신은 백그라운드 읽기와 쓰기 스캔이 성능에 영향을 미칠까 봐 걱정합니까?걱정하지 마십시오. Aerospike는 background-scan-max-rps으로 초당 기록을 조절할 수 있습니다.Aerospike 데이터베이스 노드에 약 20만 개의 대상을 클라이언트에게 전달하는 대신 경량급 바이너리 조작을 보내서 모든 최적화 비용과 성능을 고려할 수 있습니다.네가 얼마를 절약할 수 있는지 생각해 봐라!너는 영웅이 될 거야!
Reference
이 문제에 관하여(Aerospike의 서열화 또는 압축 대상은?곰곰이 생각하다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/aerospike/serialized-or-compressed-objects-with-aerospike-consider-carefully-133l텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)