Tair (Enterprise Edition) persistent memory-optimized instances use persistent memory (PMEM) to deliver large-capacity in-memory databases compatible with open source Redis. The following sections cover the test environment, tool, workloads, and results for benchmarking these instances.
Overview
Persistent memory-optimized instances use PMEM to provide large-capacity in-memory databases without relying on disks for data persistence. Every write operation is persisted directly to PMEM, maintaining the reliability of each operation. These instances cost 30% less than Redis Open-Source Edition instances while delivering almost the same throughput and latency.
For a product overview, see Persistent memory-optimized instances.
Performance at a glance
The table below shows representative QPS (queries per second) for the tair.scm.standard.32m.128d instance type across common workloads (128-byte string values).
| Workload | Operation | QPS | Average latency |
|---|---|---|---|
| Data loading | 100% write | 134,478 | 473 µs |
| Workload C | 100% read | 170,699 | 362 µs |
| Workload A | 50% read / 50% update | 141,120 | ~451 µs read, ~450 µs update |
Detailed results by data type and value size are in the Test results for data loading sections below.
Test environment
| Item | Description |
|---|---|
| Region and zone | Zhangjiakou Zone A |
| Instance architecture | Standard master-replica architecture. See Standard architecture. |
| Stress testing host | Elastic Compute Service (ECS) instance of the ecs.g6e.8xlarge type. See Overview of instance families. |
| Instance type | tair.scm.standard.32m.128d |
Test tool
YCSB (Yahoo! Cloud Serving Benchmark) is an open source Java benchmarking framework that supports multiple database types. See YCSB on GitHub for installation instructions.
By default, YCSB tests only hashes. To benchmark strings, replace the RedisClient.java file in YCSB/redis/src/main/java/site/ycsb/db/ with the custom RedisClient.java after downloading YCSB.
Complex commands for sets and sorted sets are not included in these tests because their performance characteristics depend heavily on the specific use case. Design a custom workload for sets and sorted sets based on your application requirements.
Workloads
All tests use 8 GB of data with a Zipfian key distribution, which models real-world access patterns where a small fraction of keys receives the majority of requests. Three workloads are tested:
| Workload | Operations |
|---|---|
| Data loading | 100% write (INSERT) |
| Workload C | 100% read |
| Workload A | 50% read / 50% update |
For workload definitions, see Core Workloads.
Test commands
# Load data
workload=a
./bin/ycsb load redis -s -P workloads/workload${workload} \
-p "redis.host=${server_ip}" \
-p "redis.port=${port}" \
-p "redis.password=${password}" \
-p "recordcount=${recordcount}" \
-p "operationcount=${operationcount}" \
-p "redis.timeout=30000" \
-p "redis.command_group=${command_group}" \
-p "fieldcount=${fieldcount}" \
-p "fieldlength=${fieldlength}" \
-threads ${threads} \
-p "redis.password=***:*****"
# Run Workload C (100% read)
workload=c
./bin/ycsb run redis -s -P workloads/workload${workload} \
-p "redis.host=${server_ip}" \
-p "redis.port=${port}" \
-p "redis.password=${password}" \
-p "recordcount=${recordcount}" \
-p "operationcount=${operationcount}" \
-p "redis.timeout=30000" \
-p "redis.command_group=${command_group}" \
-p "fieldcount=${fieldcount}" \
-p "fieldlength=${fieldlength}" \
-threads ${threads} \
-p "redis.password=***:*****"
# Run Workload A (50% read / 50% update)
workload=a
./bin/ycsb run redis -s -P workloads/workload${workload} \
-p "redis.host=${server_ip}" \
-p "redis.port=${port}" \
-p "redis.password=${password}" \
-p "recordcount=${recordcount}" \
-p "operationcount=${operationcount}" \
-p "redis.timeout=30000" \
-p "redis.command_group=${command_group}" \
-p "fieldcount=${fieldcount}" \
-p "fieldlength=${fieldlength}" \
-threads ${threads} \
-p "redis.password=***:*****"Parameters
| Parameter | Description |
|---|---|
server_ip | IP address of the instance |
port | Service port of the instance |
password | Authentication credential. Format depends on the account type: the default account uses the password only (for example, AUTH Password21); a custom account uses username:password format (for example, AUTH testaccount:Rp829dlwa). To reset a forgotten password, see Change or reset the password. |
recordcount | The amount of prepared data |
operationcount | The amount of data involved in the operation |
command_group | Data type to test. Run tests in this order: String, Hash, List, Set, Zset |
fieldcount | Number of fields or elements per key. Set to 1 for strings; set to 10 for all other data types |
fieldlength | Value size in bytes |
threads | Number of YCSB client threads. Tune based on the instance type |
Test metrics
| Metric | Description |
|---|---|
| QPS | Number of read and write operations processed per second |
| INSERT average latency | Mean latency of write operations (µs) |
| INSERT 99th percentile latency | The slowest latency that still falls within the fastest 99% of write operations (µs). For example, a value of 500 µs means 99% of writes complete within 500 µs. |
| READ average latency | Mean latency of read operations (µs) |
| READ 99th percentile latency | The slowest latency within the fastest 99% of read operations (µs) |
| UPDATE average latency | Mean latency of update operations (µs) |
| UPDATE 99th percentile latency | The slowest latency within the fastest 99% of update operations (µs) |
Test results for data loading
Data loading measures 100% write (INSERT) performance.
Strings
| Value length (bytes) | QPS | INSERT average latency (µs) | INSERT 99th percentile latency (µs) |
|---|---|---|---|
| 128 | 134,478 | 473 | 687 |
| 256 | 126,139 | 504 | 828 |
| 1,024 | 99,775 | 638 | 1,051 |
| 2,048 | 77,130 | 826 | 1,157 |
| 4,096 | 60,646 | 1,050 | 1,534 |
Hashes (10 fields per key)
| Value length (bytes) | QPS | INSERT average latency (µs) | INSERT 99th percentile latency (µs) |
|---|---|---|---|
| 128 | 47,353 | 1,348 | 1,885 |
| 256 | 46,716 | 1,366 | 2,181 |
| 1,024 | 27,759 | 2,297 | 2,873 |
| 2,048 | 16,605 | 3,833 | 4,923 |
Lists (10 elements per key)
| Value length (bytes) | QPS | INSERT average latency (µs) | INSERT 99th percentile latency (µs) |
|---|---|---|---|
| 128 | 64,950 | 979 | 1,310 |
| 256 | 47,157 | 1,348 | 1,752 |
| 1,024 | 26,719 | 2,386 | 3,457 |
| 2,048 | 16,714 | 3,811 | 4,751 |
| 4,096 | 10,129 | 6,279 | 7,891 |
Sets (10 members per key)
| Value length (bytes) | QPS | INSERT average latency (µs) | INSERT 99th percentile latency (µs) |
|---|---|---|---|
| 128 | 63,670 | 1,001 | 1,514 |
| 256 | 44,707 | 1,427 | 2,129 |
| 1,024 | 25,375 | 2,513 | 3,239 |
| 2,048 | 14,318 | 4,451 | 5,619 |
| 4,096 | 8,378 | 7,608 | 9,095 |
Sorted sets (10 elements per key)
| Value length (bytes) | QPS | INSERT average latency (µs) | INSERT 99th percentile latency (µs) |
|---|---|---|---|
| 128 | 40,292 | 1,585 | 2,469 |
| 256 | 34,168 | 1,869 | 2,569 |
| 1,024 | 21,347 | 2,989 | 3,905 |
| 2,048 | 12,868 | 4,956 | 6,255 |
| 4,096 | 7,864 | 8,101 | 9,599 |
Test results for Workload C
Workload C measures 100% read performance.
Strings
| Value length (bytes) | QPS | READ average latency (µs) | READ 99th percentile latency (µs) |
|---|---|---|---|
| 128 | 170,699 | 362 | 546 |
| 256 | 163,829 | 380 | 565 |
| 1,024 | 161,491 | 386 | 569 |
| 2,048 | 130,189 | 487 | 729 |
| 4,096 | 115,433 | 548 | 808 |
Hashes (10 fields per key)
| Value length (bytes) | QPS | READ average latency (µs) | READ 99th percentile latency (µs) |
|---|---|---|---|
| 128 | 96,111 | 662 | 874 |
| 256 | 86,892 | 733 | 915 |
| 1,024 | 61,608 | 1,030 | 1,293 |
| 2,048 | 37,334 | 1,696 | 2,331 |
| 4,096 | 25,943 | 2,429 | 3,319 |
Lists (10 elements per key)
| Value length (bytes) | QPS | READ average latency (µs) | READ 99th percentile latency (µs) |
|---|---|---|---|
| 128 | 105,296 | 604 | 889 |
| 256 | 97,047 | 655 | 890 |
| 1,024 | 66,384 | 955 | 1,192 |
| 2,048 | 35,796 | 1,769 | 2,461 |
| 4,096 | 26,314 | 2,392 | 3,271 |
Sets (10 members per key)
| Value length (bytes) | QPS | READ average latency (µs) | READ 99th percentile latency (µs) |
|---|---|---|---|
| 128 | 97,825 | 651 | 896 |
| 256 | 80,954 | 787 | 970 |
| 1,024 | 59,924 | 1,060 | 1,313 |
| 2,048 | 33,356 | 1,900 | 2,637 |
| 4,096 | 23,605 | 2,677 | 3,723 |
Sorted sets (10 elements per key)
| Value length (bytes) | QPS | READ average latency (µs) | READ 99th percentile latency (µs) |
|---|---|---|---|
| 128 | 58,380 | 1,093 | 1,341 |
| 256 | 56,287 | 1,133 | 1,390 |
| 1,024 | 47,468 | 1,338 | 1,688 |
| 2,048 | 30,073 | 2,096 | 2,783 |
| 4,096 | 21,850 | 2,880 | 3,765 |
Test results for Workload A
Workload A measures mixed-read/write performance: 50% reads and 50% updates.
Strings
| Value length (bytes) | QPS | READ average latency (µs) | READ 99th percentile latency (µs) | UPDATE average latency (µs) | UPDATE 99th percentile latency (µs) |
|---|---|---|---|---|---|
| 128 | 141,120 | 451 | 616 | 450 | 618 |
| 256 | 137,551 | 463 | 617 | 461 | 618 |
| 1,024 | 124,165 | 516 | 724 | 508 | 725 |
| 2,048 | 92,652 | 695 | 881 | 678 | 871 |
| 4,096 | 78,994 | 819 | 1,042 | 791 | 1,024 |
Hashes (10 fields per key)
| Value length (bytes) | QPS | READ average latency (µs) | READ 99th percentile latency (µs) | UPDATE average latency (µs) | UPDATE 99th percentile latency (µs) |
|---|---|---|---|---|---|
| 128 | 99,495 | 646 | 831 | 633 | 820 |
| 256 | 88,235 | 731 | 985 | 712 | 966 |
| 1,024 | 72,013 | 892 | 1,159 | 863 | 2,049 |
| 2,048 | 45,790 | 1,379 | 1,898 | 1,354 | 2,821 |
| 4,096 | 32,912 | 1,891 | 2,931 | 1,915 | 7,887 |
Lists (10 elements per key)
| Value length (bytes) | QPS | READ average latency (µs) | READ 99th percentile latency (µs) | UPDATE average latency (µs) | UPDATE 99th percentile latency (µs) |
|---|---|---|---|---|---|
| 128 | 71,696 | 591 | 775 | 1,185 | 1,383 |
| 256 | 66,294 | 638 | 800 | 1,281 | 1,456 |
| 1,024 | 53,402 | 791 | 1,006 | 1,581 | 1,865 |
| 2,048 | 36,519 | 1,221 | 1,581 | 2,232 | 2,831 |
| 4,096 | 28,390 | 1,618 | 2,113 | 2,803 | 3,777 |
Sets (10 members per key)
| Value length (bytes) | QPS | READ average latency (µs) | READ 99th percentile latency (µs) | UPDATE average latency (µs) | UPDATE 99th percentile latency (µs) |
|---|---|---|---|---|---|
| 128 | 66,346 | 640 | 792 | 1,282 | 1,445 |
| 256 | 60,010 | 707 | 993 | 1,415 | 1,957 |
| 1,024 | 45,359 | 933 | 1,128 | 1,858 | 2,073 |
| 2,048 | 29,027 | 1,529 | 2,021 | 2,820 | 4,507 |
| 4,096 | 21,440 | 2,144 | 2,773 | 3,726 | 5,095 |
Sorted sets (10 elements per key)
| Value length (bytes) | QPS | READ average latency (µs) | READ 99th percentile latency (µs) | UPDATE average latency (µs) | UPDATE 99th percentile latency (µs) |
|---|---|---|---|---|---|
| 128 | 49,695 | 861 | 1,050 | 1,707 | 1,912 |
| 256 | 48,036 | 891 | 1,084 | 1,763 | 1,970 |
| 1,024 | 39,795 | 1,081 | 1,386 | 2,107 | 2,563 |
| 2,048 | 28,415 | 1,597 | 1,981 | 2,855 | 3,589 |
| 4,096 | 21,317 | 2,247 | 2,821 | 3,665 | 4,787 |
What's next
Persistent memory-optimized instances — product overview and pricing
Standard architecture — architecture details for the tested configuration
Change or reset the password — manage instance credentials