在計算機并發領域編程中總是會與鎖打交道,鎖又有很多種,互斥鎖、自旋鎖等等。
鎖總是伴隨著線程、進程這樣的詞匯出現,阮一峰有 一篇文章 對這些名詞進行了簡單易懂的解釋。
我的理解是,使用線程、進程是為了實現并發從而獲得性能的提升(利用多核CPU,多臺服務器),但這種并發由于調度的不確定性,很容易出亂子,為了(在一些共享資源、關鍵節點上)不出亂子,又需要對資源加鎖,在操作這個資源時控制這種并發,將亂子消滅。
很多語言都提供了一些線程級別的鎖實現以及一些相應的工具,但在進程方面就無能為力了。而一個服務部署到生產環境,往往會部署多個實例,這種情況下,就經常會用到給不同進程用的鎖,分布式鎖便是在分布式系統中對某共享資源進行加鎖的構件。
現在來試著展示一下在Python項目中如何使用簡單的分布式互斥鎖。
不使用分布式鎖會怎樣
先用一個簡單的實例來演示一下,不使用分布式鎖會出怎樣的亂子。
假設商城系統要做秒殺活動,在redis中記錄著 count:1 的信息,到秒殺時間點的時候,會收到許多的請求,這時各應用程序去查redis中count的值,若count還大于0,則將count-1,這樣其他請求就不再能秒殺到了。
# -*- coding: utf-8 -*-import osimport arrowimport redisfrom multiprocessing import PoolHOT_KEY = 'count'r = redis.Redis(host='localhost', port=6379)def seckilling(): name = os.getpid() v = r.get(HOT_KEY) if int(v) > 0: print name, ' decr redis.' r.decr(HOT_KEY) else: print name, ' can not set redis.', vdef run_without_lock(name): while True: if arrow.now().second % 5 == 0: seckilling() returnif __name__ == '__main__': p = Pool(16) r.set(HOT_KEY, 1) for i in range(16): p.apply_async(run_without_lock, args=(i, )) print 'now 16 processes are going to get lock!' p.close() p.join() print('All subprocesses done.')
以上代碼使用多進程來模仿這種并發請求場景,程序開始的時候將count設為1,之后各進程開始進入等待,當秒數為5的時候,所有進程同時去訪問秒殺函數,來看一下效果:
運行結果
新聞熱點
疑難解答