python 写 redis 为何如此的慢????

2015-11-30 19:23:46 +08:00
 larkifly

代码如下

import redis
dd = redis.ConnectionPool(max_connections=100, socket_keepalive=True)
aa = redis.Redis(connection_pool=dd)
import time
temps = 'ksljdfldksjfklsldkfjkdsjflkdsjflkdsklskdjfljewl'
for i in range(1, 100000):
    aa.set(temps+str(i), temps)

这段代码运行完,花了七秒多?一定是我姿势不对,不应该这么慢啊

6134 次点击
所在节点    Python
21 条回复
kikyous
2015-11-30 19:52:43 +08:00
你空循环试试
kikyous
2015-11-30 19:54:13 +08:00
字符串相加代价很高,忘了是哪个语言了😁
wy315700
2015-11-30 19:56:01 +08:00
hiredis 装了吗
JamesRuan
2015-11-30 20:04:45 +08:00
@kikyous python 的 str 是 immutable 的,相连是需要复制整个数据结构的。
wenbinwu
2015-11-30 20:06:54 +08:00
用 pipeline
lichun
2015-11-30 20:20:12 +08:00
In [15]: pool = redis.ConnectionPool(host='localhost', port=6379, db=0)

In [16]: r = redis.Redis(connection_pool=pool)

In [17]: def test_redis():
....: for i in range(100000):
....: r.set(str(i), 'test')
....:

In [18]: %time test_redis()
CPU times: user 5.9 s, sys: 1.53 s, total: 7.42 s
Wall time: 10.9 s
est
2015-11-30 20:25:52 +08:00
range 改 xrange 试试。
lichun
2015-11-30 20:34:09 +08:00
@est
@kikyous

并不是字符串相加和 range 的原因,估计是 redis 驱动的锅
larkifly
2015-11-30 20:51:43 +08:00
@kikyous
@wy315700
@JamesRuan
@wenbinwu
@lichun
@est

目前看来是 redis-py 本身的问题,用 pipeline 效率会提升很多。经过实际的测试发现, redis-py 只开启了一个连接连到 redis-server ,那么,大量写的时候,会出现锁、排队的情况。而且, redis-py 的 keepalive 并没有让我感觉到使用的 tcp 长链。如果是长链,那么效果应该和 pipeline 差不多,即使差,也不会差很多。
sunus
2015-11-30 20:56:55 +08:00
用 pipeline 应该能到 2s 以内
odirus
2015-11-30 21:10:22 +08:00
我现在已经很少直接操作 redis 了,都是配合 lua 一起使用,并发性得到大大地提升。
cheng007
2015-11-30 21:15:44 +08:00
Macbook air 用了 11s , 1s 写 1w 次算很慢吗?
binux
2015-11-30 21:30:53 +08:00
不管换什么语言, aa.set 都需要等 TCP 包一个来回, 即使 keep-alive, 即使 redis 很快, 但是这个时间放大到 100000 次. 我觉得这个速度很正常.
tabris17
2015-11-30 21:58:32 +08:00
Tcp 通信的开销,很正常吧。所以才要 pipline
zts1993
2015-11-30 22:43:28 +08:00
我会说 Jedis 局域网内只有 7k ops 么。。你这个已经算快的了,,要想快 pipeline 和多线程。。。
lenran
2015-11-30 22:48:24 +08:00
@binux 13 楼正解
sujin190
2015-11-30 23:19:05 +08:00
1 万多每秒,单线程,可以了吧,又不是内存写
rockivy
2015-12-01 10:05:48 +08:00
批量操作一定要使用 pipeline.
不久前刚做过一个小测试, 下面的 blog 是我的测试记录
http://www.rockyqi.net/redis-intro-and-a-simple-performance-test-for-batch-operations.html
fordoo
2015-12-01 10:08:56 +08:00
试试 low level 的 credis 速度直逼 pylibmc
latyas
2015-12-01 11:22:15 +08:00
问题略有问题,要想知道是不是 python 的坑,参考如下代码
单连接单线程的情况

```python
import socket
import time


conn = socket.socket()
conn.connect(('127.0.0.1', 6379))

_ = time.time()
for i in range(100000):
#print(i)
foo = 'ksljdfldksjfklsldkfjkdsjflkdsjflkdsklskdjfljewl' + str(i)
bar = 'ksljdfldksjfklsldkfjkdsjflkdsjflkdsklskdjfljewl'
command = 'SET %s %s\r\n' % (foo, bar)
conn.send(command.encode('utf-8'))
print('total', time.time() - _)
```


```shell
total 0.10007500648498535
```

开 10 个 worker 的进程池, 10 个 tcp 链接

```python
import socket
import time
import multiprocessing

def process(n):
conn = socket.socket()
conn.connect(('127.0.0.1', 6379))
for i in range(10000):
#print(i)
foo = 'ksljdfldksjfklsldkfjkdsjflkdsjflkdsklskdjfljewl' + str(i)
bar = 'ksljdfldksjfklsldkfjkdsjflkdsjflkdsklskdjfljewl'
command = 'SET %s %s\r\n' % (foo, bar)
conn.send(command.encode('utf-8'))

pool = multiprocessing.Pool(10)
_ = time.time()
pool.map(process, range(10))
print('total', time.time() - _)
```

```shell
total 0.029608488082885742
```


如果这么慢,是不是驱动上有坑?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/240098

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX