語言平台: 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)
