最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python使用分布式鎖的代碼演示示例

 更新時(shí)間:2018年07月30日 08:38:06   作者:古二白  
這篇文章主要介紹了Python使用分布式鎖的代碼演示,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

在計(jì)算機(jī)并發(fā)領(lǐng)域編程中總是會(huì)與鎖打交道,鎖又有很多種,互斥鎖、自旋鎖等等。

鎖總是伴隨著線程、進(jìn)程這樣的詞匯出現(xiàn),阮一峰有 一篇文章 對(duì)這些名詞進(jìn)行了簡(jiǎn)單易懂的解釋。

我的理解是,使用線程、進(jìn)程是為了實(shí)現(xiàn)并發(fā)從而獲得性能的提升(利用多核CPU,多臺(tái)服務(wù)器),但這種并發(fā)由于調(diào)度的不確定性,很容易出亂子,為了(在一些共享資源、關(guān)鍵節(jié)點(diǎn)上)不出亂子,又需要對(duì)資源加鎖,在操作這個(gè)資源時(shí)控制這種并發(fā),將亂子消滅。

很多語(yǔ)言都提供了一些線程級(jí)別的鎖實(shí)現(xiàn)以及一些相應(yīng)的工具,但在進(jìn)程方面就無能為力了。而一個(gè)服務(wù)部署到生產(chǎn)環(huán)境,往往會(huì)部署多個(gè)實(shí)例,這種情況下,就經(jīng)常會(huì)用到給不同進(jìn)程用的鎖,分布式鎖便是在分布式系統(tǒng)中對(duì)某共享資源進(jìn)行加鎖的構(gòu)件。

現(xiàn)在來試著展示一下在Python項(xiàng)目中如何使用簡(jiǎn)單的分布式互斥鎖。

不使用分布式鎖會(huì)怎樣

先用一個(gè)簡(jiǎn)單的實(shí)例來演示一下,不使用分布式鎖會(huì)出怎樣的亂子。

假設(shè)商城系統(tǒng)要做秒殺活動(dòng),在redis中記錄著 count:1 的信息,到秒殺時(shí)間點(diǎn)的時(shí)候,會(huì)收到許多的請(qǐng)求,這時(shí)各應(yīng)用程序去查redis中count的值,若count還大于0,則將count-1,這樣其他請(qǐng)求就不再能秒殺到了。

# -*- coding: utf-8 -*-
import os
import arrow
import redis
from multiprocessing import Pool

HOT_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.', v

def run_without_lock(name):
  while True:
    if arrow.now().second % 5 == 0:
      seckilling()
      return

if __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.')

以上代碼使用多進(jìn)程來模仿這種并發(fā)請(qǐng)求場(chǎng)景,程序開始的時(shí)候?qū)ount設(shè)為1,之后各進(jìn)程開始進(jìn)入等待,當(dāng)秒數(shù)為5的時(shí)候,所有進(jìn)程同時(shí)去訪問秒殺函數(shù),來看一下效果:

運(yùn)行結(jié)果

redis查詢展示

從程序打印與查redis的結(jié)果來說并未如愿,本來秒殺商品只有一件,但卻被成功搶購(gòu)到了4次。這是由于各進(jìn)程在get count的值時(shí),對(duì)redis值更新的指令已經(jīng)發(fā)出而還未進(jìn)行完畢,會(huì)讓其他進(jìn)程認(rèn)為自己可以購(gòu)得。

這種問題可歸為 不可重復(fù)讀 種類的數(shù)據(jù)并發(fā)問題。

在這種毫無保護(hù)的情況下,其他常見并發(fā)問題幻讀、臟讀、第一第二類丟失更新等都有可能發(fā)生,這里不再一一舉例。

使用ZooKeeper作分布式鎖

作為致力于解決分布式協(xié)同問題的知名工具,利用zookeeper提供的API和它對(duì)于節(jié)點(diǎn)唯一性與順序一致性的保證可以實(shí)現(xiàn)分式式鎖。

實(shí)現(xiàn)思路為,各進(jìn)程去創(chuàng)建 /exclusive_lock/lock 的結(jié)點(diǎn),zookeeper保證只有一個(gè)client可以創(chuàng)建成功,那么便認(rèn)為創(chuàng)建成功的那個(gè)client獲得了鎖,當(dāng)它處理完業(yè)務(wù)后,將該node刪除,其他client會(huì)監(jiān)聽到這個(gè)事件,并再次嘗試創(chuàng)建該節(jié)點(diǎn),如此進(jìn)行下去。

Kazoo 庫(kù)實(shí)現(xiàn)了這種Lock,使用起來非常簡(jiǎn)單,編程人員可以不用再去自己實(shí)現(xiàn)acquire,release等鎖的通用接口。

同時(shí)在Python中,對(duì)鎖的使用往往可以通過優(yōu)雅的上下文管理器with。

def run_with_zk_lock(name):
  zk = KazooClient()
  zk.start()
  lock = zk.Lock("/lockpath", "my-identifier")
  while True:
    if arrow.now().second % 5 == 0:
      with lock:
        seckilling()
        return

使用zk結(jié)果

redis查詢展示

當(dāng)秒殺發(fā)生時(shí),只有獲得鎖的進(jìn)程可以去進(jìn)行秒殺操作。

在鎖的幫助下,程序按照預(yù)想的方式運(yùn)行了。

使用redis作分布式鎖

在redis的網(wǎng)站有一篇文章 專門介紹如何使用redis作為分布式鎖,文尾還附帶了對(duì)此文章的反對(duì)文章以及再次回?fù)舻奈恼拢悬c(diǎn)精彩。

文章提到了一個(gè)redlock的分布式鎖設(shè)計(jì)。

設(shè)置鎖的redis命令為 SET resource_name my_random_value NX PX 30000 ,當(dāng)加NX參數(shù)時(shí),若resouce_name不存在才會(huì)創(chuàng)建,若不存在則會(huì)向client返回不同的結(jié)果,利用這個(gè)機(jī)制,便只有一個(gè)client可以set成功,就像上面的zk一樣了。

但是,實(shí)現(xiàn)這樣一個(gè)分布式鎖遠(yuǎn)不止這么簡(jiǎn)單,redis并不像zk一樣是一個(gè)分布式協(xié)同工具,會(huì)向client做出分布式中各種一致性及容錯(cuò)、可用性的保證。

redis本身也是集群部署的,它們之間有著異步復(fù)制時(shí)間差、容錯(cuò)等問題可能會(huì)出現(xiàn),要真正做到這個(gè)鎖的實(shí)現(xiàn)在線上大規(guī)模分布式系統(tǒng)中可用,真的是要考慮各種情況,很不容易。

關(guān)于如何在語(yǔ)言上實(shí)現(xiàn)一個(gè)鎖的接口,redlock的原理與代碼實(shí)現(xiàn),以及上述kazoo包里實(shí)現(xiàn)lock的源碼,我會(huì)在另一篇專門的文章中說一下。

redlock-py 包是python語(yǔ)言中對(duì)上述文章的實(shí)現(xiàn),我們現(xiàn)在使用它來進(jìn)行嘗試。

rlock = RedLock([{"host": "localhost", "port": 6379, "db": 0}, ])

def run_with_redis_lock(name):
  while True:
    if arrow.now().second % 5 == 0:
      with rlock:
        seckilling()
        return

redis鎖運(yùn)行結(jié)果

運(yùn)行結(jié)果和上面使用zk一樣,符合程序設(shè)計(jì)預(yù)期。

以上只是基于python語(yǔ)言的一些代碼展示,通過使用兩個(gè)第三方包,來使用分布式鎖來避免并發(fā)程序中混亂的產(chǎn)生。

但其實(shí)這中間是有一個(gè)斷層的,即,這兩個(gè)工具都是提供了一個(gè)機(jī)制,而并不是直接對(duì)外提供了操作鎖的API,那么如何利用這個(gè)機(jī)制來實(shí)現(xiàn)這樣的鎖正是這兩個(gè)第三方做的事情。

簡(jiǎn)單看過它們實(shí)現(xiàn)的源碼,以及threading中一些lock的代碼,發(fā)現(xiàn)在鎖的實(shí)現(xiàn)上是有著共通之處的,都有通用的acquire與release方法,然后將 enter 與 exit 指向前面兩個(gè)方法來實(shí)現(xiàn)上下文管理器with的用法。

此外,還可以利用關(guān)系型數(shù)據(jù)庫(kù)如MySQL固有的鎖機(jī)制來作為分布式鎖,但由于數(shù)據(jù)庫(kù)往往是系統(tǒng)的瓶頸所在,沒有必要為它引入不必要的壓力。同時(shí),MySQL中的鎖、隔離級(jí)別也有一大堆可說的,在github上找了一下也并未找到一個(gè)成熟的像上面的基于MySQL實(shí)現(xiàn)的對(duì)外暴露鎖通用API的第三方包,故未能在上面加以展示。

想要說清楚這個(gè)事情并沒有那么容易,之后我會(huì)嘗試搞清楚如何寫一個(gè)比較地道的鎖,并對(duì)上面兩個(gè)第三方包的具體實(shí)現(xiàn)加以研究,爭(zhēng)取把這個(gè)斷層補(bǔ)上。之后,或許可以嘗試實(shí)現(xiàn)一下基于MySQL的類似第三方包,這需要對(duì)MySQL的一些機(jī)制搞得更加清楚才行。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 怎么解決pycharm license Acti的方法

    怎么解決pycharm license Acti的方法

    這篇文章主要介紹了怎么解決pycharm license Acti的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • 說一說Python logging

    說一說Python logging

    這篇文章主要和大家聊一聊Python logging,Python logging是什么,Python logging的作用是什么,感興趣的小伙伴們可以參考一下
    2016-04-04
  • Python字典刪除鍵值對(duì)和元素的四種方法(小結(jié))

    Python字典刪除鍵值對(duì)和元素的四種方法(小結(jié))

    刪除列表或者字符串元素的方法不止一種,同樣,刪除字典元素的方法也不止一種,本文主要介紹python中刪除字典元素的四種方法:1、使用del語(yǔ)句;2、使用clear();3、使用pop();4、使用popitem()。感興趣的可以了解一下
    2021-12-12
  • Jupyter Lab無法打開終端窗口的解決方法

    Jupyter Lab無法打開終端窗口的解決方法

    本文主要介紹了Jupyter Lab無法打開終端窗口的解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • Flask搭建api服務(wù)的實(shí)現(xiàn)步驟

    Flask搭建api服務(wù)的實(shí)現(xiàn)步驟

    本文主要介紹了Flask搭建api服務(wù)的實(shí)現(xiàn)步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • python使用正則來處理各種匹配問題

    python使用正則來處理各種匹配問題

    這篇文章主要介紹了python使用正則來處理各種匹配問題,本文通過實(shí)例代碼給大家講解的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-12-12
  • python使用KNN算法識(shí)別手寫數(shù)字

    python使用KNN算法識(shí)別手寫數(shù)字

    這篇文章主要為大家詳細(xì)介紹了python使用KNN算法識(shí)別手寫數(shù)字,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • Sentry的安裝、配置、使用教程(Sentry日志手機(jī)系統(tǒng))

    Sentry的安裝、配置、使用教程(Sentry日志手機(jī)系統(tǒng))

    Sentry?是一個(gè)實(shí)時(shí)事件日志記錄和聚合平臺(tái),由于ExceptionLess官方提供的客戶端只有.Net/.NetCore平臺(tái)和js的,本文繼續(xù)介紹另一個(gè)日志收集系統(tǒng)Sentry,感興趣的朋友一起看看吧
    2022-07-07
  • Python對(duì)FTP交互封裝的實(shí)現(xiàn)

    Python對(duì)FTP交互封裝的實(shí)現(xiàn)

    本文主要介紹了Python對(duì)FTP交互封裝的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • Python?SDK實(shí)現(xiàn)私服上傳下載的示例

    Python?SDK實(shí)現(xiàn)私服上傳下載的示例

    本文主要介紹了Python?SDK實(shí)現(xiàn)私服上傳下載的示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下<BR>
    2021-11-11

最新評(píng)論

白城市| 平凉市| 陇川县| 老河口市| 丹凤县| 二连浩特市| 武城县| 深州市| 繁昌县| 班戈县| 股票| 平塘县| 寿阳县| 漾濞| 日照市| 萨嘎县| 金秀| 明溪县| 光泽县| 鄯善县| 霍林郭勒市| 沐川县| 睢宁县| 大同市| 永济市| 博客| 禄丰县| 堆龙德庆县| 龙门县| 昆明市| 子长县| 樟树市| 桑植县| 剑河县| 灵璧县| 阿勒泰市| 太仆寺旗| 松阳县| 额济纳旗| 福泉市| 台北县|