语言平台: Python 2.6
Lib: redis.py (latest)
安装: 参官网
1. StrictRedis
import redis r = redis.StrictRedis(host='192.168.0.110', password=pwd, port=6379,db=0)
StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令,Redis是StrictRedis的子类。
2. Redis
import redis r = redis.Redis(host='192.168.0.110', password=pwd, port=6379,db=0)
3. 连接池
pool = redis.ConnectionPool(host='host',password='prod', port=6366,db=0) r = redis.Redis(connection_pool=pool) pipe = r.pipeline()
pipe.set('one', 'first') pipe.get(‘one’) pipe.execute() for I in xrange(1000000): pipe.set(‘GRP1:GRP2:GRP3:Key’+str(i), i) pipe.execute()
redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池.
redis号称最大能达到10w/s级别set性能。如何达到不详。不过这里做了一个测试来验证什么样的情况下可以达到或者接近官方宣称的水平。
** 运行环境: Opteron 4Core 2.3G/4G RAM/500G disk
下表是本人最近的一个测试结果,供参考。(基于百万次set操作)
redis hiredis Redisco pipeline 多进程+pipeline
531 346 310 51 28.9(4x)/23(8x)
- redis, 原生REDIS连接方式进行单次写入。
- hiredis, 官方维护的一份更高性能的redis lib,安装后即可,不需要引入。
- 多进程,即设想在数据量比较大的情况下,将插入的队列平均切割给进程来提高性能
下表是针对多进程不同数量级和不同进程数下的性能表现。可以看出来,将最小核心执行数量控制在3~4万次的整数倍之间,能够达到最好的效率。
指令数 |
进程数 |
单进程时间(最大) |
单进程时间(最小) |
总运行时间 |
每秒指令数(万) |
每进程指令数 |
5,000,000 |
4 |
02:29.9 |
02:27.9 |
02:46.6 |
3.0 |
125 |
5,000,000 |
8 |
02:16.6 |
01:53.2 |
02:24.1 |
3.5 |
62.5 |
5,000,000 |
16 |
01:54.7 |
01:28.0 |
02:00.5 |
4.2 |
31.25 |
5,000,000 |
20 |
01:51.0 |
01:17.9 |
02:00.1 |
4.2 |
25 |
5,000,000 |
50 |
01:46.1 |
00:59.5 |
02:09.7 |
3.9 |
10 |
5,000,000 |
100 |
00:05.6 |
04:48.6 |
06:32.0 |
1.3 |
5 |
100,000 |
4 |
|
|
00:03.3 |
3.0 |
2.5 |
100,000 |
2 |
|
|
00:07.6 |
1.3 |
5.0 |
100,000 |
1 |
|
|
00:04.8 |
2.1 |
10.0 |
100,000 |
8 |
|
|
00:04.4 |
2.3 |
1.3 |
100,000 |
3 |
|
|
00:03.1 |
3.2 |
3.3 |
100,000 |
16 |
|
|
00:07.1 |
1.4 |
0.6 |
- 结论: 在数量级达到万以上时,使用连接池方式可以达到20,000次每秒性能。继续使用多进程的情况下,性能提升2倍以上左右,达到4万次每秒,若核心越多,速度越高,性能会越好。
所以,大数据量情况下,1,使用pipeline, 2, 使用多进程, 3, 正确分配数据量给进程, 你将得到单机4w+级别的写入性能,已经足够强大了。
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import datetime 4 5 def test1(string, cnt): 6 import redis 7 r = redis.StrictRedis(host=cfg['host'],password=cfg['pwd'], port=cfg['port'],db=cfg['db']) 8 now = datetime.datetime.now() 9 for i in range(0, cnt): 10 r.set(i, string) 11 print datetime.datetime.now() - now 12 13 def test2(string, cnt): 14 import redisco 15 from redisco.containers import Hash,List,SortedSet,Set 16 r = redisco.connection_setup(host=cfg['host'],password=cfg['pwd'], port=cfg['port'],db=cfg['db']) 17 h = Hash("h") 18 now = datetime.datetime.now() 19 for i in range(0, cnt): 20 h[i] = string 21 print datetime.datetime.now() - now 22 23 def test3(string, cnt): 24 import redis 25 #redis.ConnectionPool(host=host, password=passwd, port=port, db=db, socket_timeout=3, max_connections=10) # max_connection default 2**31 26 pool = redis.ConnectionPool(host=cfg['host'],password=cfg['pwd'], port=cfg['port'],db=cfg['db']) 27 r = redis.Redis(connection_pool=pool) 28 pipe = r.pipeline() 29 now = datetime.datetime.now() 30 for i in xrange(cnt): 31 pipe.set(i, string) 32 pipe.execute() 33 print datetime.datetime.now() - now 34 35 def sliceArr(cnt, n): 36 x = [] 37 for i in range(n): 38 x.append((cnt*i/n,cnt*(i+1)/n)) 39 return x 40 41 def test4(q): 42 import redis 43 #redis.ConnectionPool(host=host, password=passwd, port=port, db=db, socket_timeout=3, max_connections=10) # max_connection default 2**31 44 pool = redis.ConnectionPool(host=cfg['host'],password=cfg['pwd'], port=cfg['port'],db=cfg['db']) 45 r = redis.Redis(connection_pool=pool) 46 pipe = r.pipeline() 47 now = datetime.datetime.now() 48 for i in xrange(q[0], q[1]): 49 pipe.set(i, string) 50 pipe.execute() 51 print datetime.datetime.now() - now 52 53 def test5(string, cnt): 54 from multiprocessing import Pool 55 import subprocess as sub 56 import socket 57 now1 = datetime.datetime.now() 58 n=16 59 #for t in sliceArr(cnt, 4): 60 if 1: 61 pool = Pool(n) 62 pool.map(test4, sliceArr(cnt, n)) 63 pool.close() 64 pool.join() 65 print datetime.datetime.now() - now1 66 67 if __name__=="__main__": 68 cfg = {'host':'xxx','pwd':'prod','port':'6366','db':1} 69 string = "0" 70 cnt = 1000000 71 #test1(string, cnt) 72 #test2(string, cnt) 73 #test3(string, cnt) 74 test5(string, cnt)