所以我有一个简单的Redis数据库。它包含136689个键,其值是包含27个字段的哈希映射。我正在通过服务器节点上的Python接口访问该表,并且每次调用需要加载大约1000-1500个值(最终,我将看到每秒大约10个请求)。一个简单的调用看起来像这样:
# below keys is a list of approximately 1000 integers,
# not all of which are in the table
import redis
db = redis.StrictRedis(
host='127.0.0.1',
port=6379,
db=0,
socket_timeout=1,
socket_connection_timeout=1,
decode_responses=True
)
with db.pipeline() as pipe:
for key in keys:
pipe.hgetall(key)
results = zip(keys,pipe.execute())
此操作的总时间约为328毫秒,每个请求的平均时间约为0.25毫秒。
问题:对于小型数据库,每秒查询相对较少,这非常慢。我的配置或调用服务器的方式有问题吗?可以做些什么使它更快吗?我不希望表变得更大,所以我非常高兴牺牲磁盘空间来提高速度。
在每个键上(没有管道)调用hget
的速度较慢(如预期的那样),并显示时间分布是双峰的。较小的峰值对应于不在表中的键,而较大的峰值对应于在表中的键。
我的conf文件如下:
port 6379
daemonize yes
save ""
bind 127.0.0.1
tcp-keepalive 300
dbfilename mytable.rdb
dir .
rdbcompression yes
appendfsync no
no-appendfsync-on-rewrite yes
loglevel notice
我使用以下命令启动服务器:
> echo never > /sys/kernel/mm/transparent_hugepage/enabled
> redis-server myconf.conf
我还用redis-cli --intrinsic-latency 100
测量了固有延迟,它给出了:
Max latency so far: 1 microseconds.
Max latency so far: 10 microseconds.
Max latency so far: 11 microseconds.
Max latency so far: 12 microseconds.
Max latency so far: 18 microseconds.
Max latency so far: 32 microseconds.
Max latency so far: 34 microseconds.
Max latency so far: 38 microseconds.
Max latency so far: 48 microseconds.
Max latency so far: 52 microseconds.
Max latency so far: 60 microseconds.
Max latency so far: 75 microseconds.
Max latency so far: 94 microseconds.
Max latency so far: 120 microseconds.
Max latency so far: 281 microseconds.
Max latency so far: 413 microseconds.
Max latency so far: 618 microseconds.
1719069639 total runs (avg latency: 0.0582 microseconds / 58.17 nanoseconds per run).
Worst run took 10624x longer than the average latency.
这表明我应该能够获得更好的延迟。但是,当我使用以下命令检查服务器延迟时:> redis-cli --latency -h 127.0.0.1 -p 6379
我得到了min: 0, max: 2, avg: 0.26 (2475 samples)
这似乎表明服务器的延迟时间约为0.25ms,但这似乎表明我从Python看到的每个请求的延迟时间与CLI相同,但似乎都非常慢。
与每个键相关联的哈希图(解码后)的大小约为1200个字节。因此我运行了以下基准测试
redis-benchmark -h 127.0.0.1 -p 6379 -d 1500 hmset hgetall myhash rand_int rand_string
====== hmset hgetall myhash rand_int rand_string ======
100000 requests completed in 1.45 seconds
50 parallel clients
1500 bytes payload
keep alive: 1
100.00% <= 1 milliseconds
100.00% <= 1 milliseconds
69060.77 requests per second
这似乎支持我的延迟很高,但并没有真正告诉我原因。
我从使用Redis的方式得出的结论之一是,我们不应该将每个事务存储在一个哈希中。与一次交易一样,一个哈希。
对于每个hget请求,我们都有一个网络连接正在减慢查询速度。
我认为Redis的设计方式是将所有内容存储在一个哈希中,就像将所有事务存储在一个哈希中一样。
此外,粒度数据可以作为JSON存储在每个值中。
我获取所有哈希值的时间与获取一个哈希值中存储的所有值所花费的时间无法比较。
对于第一个方法,对于140mb的数据,它花了3秒(遍历所有键),而第二个方法,它花了0.008秒(使所有内容仅存储在一个哈希中)。