2012-11-17 81 views
4

我正在使用Python的Redis服務器。我的應用程序是多線程的(每個進程使用20-32個線程),我也是 我在不同的機器上運行應用程序。python Redis Connections

我注意到,有時Redis cpu的使用率是100%,而Redis服務器變得反應遲鈍。

我想每個應用程序使用1連接總共4個連接池。 因此,例如,如果我最多在20臺計算機上運行我的應用程序,則應該有20 * 4 = 80個連接到redis服務器的 連接。

POOL = redis.ConnectionPool(max_connections=4, host='192.168.1.1', db=1, port=6379) 
R_SERVER = redis.Redis(connection_pool=POOL) 

class Worker(Thread): 

    def __init__(self): 
     self.start() 

    def run(self): 
     while True: 
      key = R_SERVER.randomkey() 
      if not key: break 
      value = R_SERVER.get(key) 


    def _do_something(self, value): 
     # do something with value 
     pass 

if __name__ = '__main__': 
    num_threads = 20 
    workers = [Worker() for _ in range(num_threads)] 
    for w in workers: 
     w.join() 

上述代碼應運行20個線程在執行命令時獲得來自最大大小爲4的連接池的連接。

當連接被釋放?

根據這個代碼(https://github.com/andymccurdy/redis-py/blob/master/redis/client.py):

#### COMMAND EXECUTION AND PROTOCOL PARSING #### 
def execute_command(self, *args, **options): 
    "Execute a command and return a parsed response" 
    pool = self.connection_pool 
    command_name = args[0] 
    connection = pool.get_connection(command_name, **options) 
    try: 
     connection.send_command(*args) 
     return self.parse_response(connection, command_name, **options) 
    except ConnectionError: 
     connection.disconnect() 
     connection.send_command(*args) 
     return self.parse_response(connection, command_name, **options) 
    finally: 
     pool.release(connection) 

每個命令執行後,該連接被釋放,並得到回池中

有人可以驗證我已經明白這個想法正確並且上述示例代碼將按照描述工作?

因爲當我看到Redis的連接,總有超過4

編輯:我只注意到,該函數之前,終於return語句代碼。那麼最後的目的是什麼?

+0

finally塊得到執行,無論它們是否是一個例外。這是一個DRY用例。 –

+1

您提到Redis服務器有時無響應。你使用Windows?如果是這樣,Windows版本會將數據庫異步保存到磁盤,這會導致Redis掛起,直到完成。 –

+1

即使在unix環境下,節約成本也很高。如果您正在使用RDB轉儲序列化策略,則Redis會將內存數據庫副本寫出來。如果您的數據庫大小大於1/2可用內存,則在嘗試執行此操作時會發生不良情況。如果這是問題,請嘗試使用AOF策略或關閉序列化。 –

回答

0

正如Matthew Scragg所提到的,finally子句在測試結束時執行。在這種特殊情況下,它用於在連接完成後將連接釋放回游泳池,而不是將其懸空。

至於沒有反應,請看你的服務器在做什麼。你的Redis實例的內存限制是多少?你多久保存一次磁盤?您是否在基於Xen的虛擬機(如AWS實例)上運行?你是否正在運行復制,如果是的話,有多少個奴隸,他們是否處於良好狀態,或者他們經常要求完全同步數據?你的任何命令是否「保存」?

您可以通過使用命令行界面來回答其中的一些問題。例如 redis-cli info persistence會告訴你有關保存到磁盤的過程的信息,redis-cli info memory會告訴你關於你的內存消耗。

獲取持久性信息時,您要具體查看rdb_last_bgsave_statusrdb_last_bgsave_time_sec。這些會告訴你最後一次保存是否成功以及需要多長時間。需要的時間越長,遇到資源問題的可能性就越高,遇到可能顯示爲無響應的減速的可能性越高。

0

雖然在它之前有一個return語句,但最終塊將始終運行。你可以看看redis-py/connection.py,pool.release(connection)只把連接放到可用連接池中,所以連接仍然存在。 關於redis服務器cpu使用情況,您的應用將始終發送請求並且沒有休息或休眠,所以它只是使用越來越多的cpus,而不是內存。和CPU使用率與打開的文件數量沒有關係。