一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - Python使用分布式鎖的代碼演示示例

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

2021-03-23 00:48古二白 Python

這篇文章主要介紹了Python使用分布式鎖的代碼演示,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

在計算機并發領域編程中總是會與鎖打交道,鎖又有很多種,互斥鎖、自旋鎖等等。

鎖總是伴隨著線程、進程這樣的詞匯出現,阮一峰有 一篇文章 對這些名詞進行了簡單易懂的解釋。

我的理解是,使用線程、進程是為了實現并發從而獲得性能的提升(利用多核cpu,多臺服務器),但這種并發由于調度的不確定性,很容易出亂子,為了(在一些共享資源、關鍵節點上)不出亂子,又需要對資源加鎖,在操作這個資源時控制這種并發,將亂子消滅。

很多語言都提供了一些線程級別的鎖實現以及一些相應的工具,但在進程方面就無能為力了。而一個服務部署到生產環境,往往會部署多個實例,這種情況下,就經常會用到給不同進程用的鎖,分布式鎖便是在分布式系統中對某共享資源進行加鎖的構件。

現在來試著展示一下在python項目中如何使用簡單的分布式互斥鎖。

不使用分布式鎖會怎樣

先用一個簡單的實例來演示一下,不使用分布式鎖會出怎樣的亂子。

假設商城系統要做秒殺活動,在redis中記錄著 count:1 的信息,到秒殺時間點的時候,會收到許多的請求,這時各應用程序去查redis中count的值,若count還大于0,則將count-1,這樣其他請求就不再能秒殺到了。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# -*- 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.')

以上代碼使用多進程來模仿這種并發請求場景,程序開始的時候將count設為1,之后各進程開始進入等待,當秒數為5的時候,所有進程同時去訪問秒殺函數,來看一下效果:

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

運行結果

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

redis查詢展示

從程序打印與查redis的結果來說并未如愿,本來秒殺商品只有一件,但卻被成功搶購到了4次。這是由于各進程在get count的值時,對redis值更新的指令已經發出而還未進行完畢,會讓其他進程認為自己可以購得。

這種問題可歸為 不可重復讀 種類的數據并發問題。

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

使用zookeeper作分布式鎖

作為致力于解決分布式協同問題的知名工具,利用zookeeper提供的api和它對于節點唯一性與順序一致性的保證可以實現分式式鎖。

實現思路為,各進程去創建 /exclusive_lock/lock 的結點,zookeeper保證只有一個client可以創建成功,那么便認為創建成功的那個client獲得了鎖,當它處理完業務后,將該node刪除,其他client會監聽到這個事件,并再次嘗試創建該節點,如此進行下去。

kazoo 庫實現了這種lock,使用起來非常簡單,編程人員可以不用再去自己實現acquire,release等鎖的通用接口。

同時在python中,對鎖的使用往往可以通過優雅的上下文管理器with。

?
1
2
3
4
5
6
7
8
9
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

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

使用zk結果

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

redis查詢展示

當秒殺發生時,只有獲得鎖的進程可以去進行秒殺操作。

在鎖的幫助下,程序按照預想的方式運行了。

使用redis作分布式鎖

在redis的網站有 一篇文章 專門介紹如何使用redis作為分布式鎖,文尾還附帶了對此文章的反對文章以及再次回擊的文章,有點精彩。

文章提到了一個redlock的分布式鎖設計。

設置鎖的redis命令為 set resource_name my_random_value nx px 30000 ,當加nx參數時,若resouce_name不存在才會創建,若不存在則會向client返回不同的結果,利用這個機制,便只有一個client可以set成功,就像上面的zk一樣了。

但是,實現這樣一個分布式鎖遠不止這么簡單,redis并不像zk一樣是一個分布式協同工具,會向client做出分布式中各種一致性及容錯、可用性的保證。

redis本身也是集群部署的,它們之間有著異步復制時間差、容錯等問題可能會出現,要真正做到這個鎖的實現在線上大規模分布式系統中可用,真的是要考慮各種情況,很不容易。

關于如何在語言上實現一個鎖的接口,redlock的原理與代碼實現,以及上述kazoo包里實現lock的源碼,我會在另一篇專門的文章中說一下。

redlock-py 包是python語言中對上述文章的實現,我們現在使用它來進行嘗試。

?
1
2
3
4
5
6
7
8
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

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

redis鎖運行結果

運行結果和上面使用zk一樣,符合程序設計預期。

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

但其實這中間是有一個斷層的,即,這兩個工具都是提供了一個機制,而并不是直接對外提供了操作鎖的api,那么如何利用這個機制來實現這樣的鎖正是這兩個第三方做的事情。

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

此外,還可以利用關系型數據庫如mysql固有的鎖機制來作為分布式鎖,但由于數據庫往往是系統的瓶頸所在,沒有必要為它引入不必要的壓力。同時,mysql中的鎖、隔離級別也有一大堆可說的,在github上找了一下也并未找到一個成熟的像上面的基于mysql實現的對外暴露鎖通用api的第三方包,故未能在上面加以展示。

想要說清楚這個事情并沒有那么容易,之后我會嘗試搞清楚如何寫一個比較地道的鎖,并對上面兩個第三方包的具體實現加以研究,爭取把這個斷層補上。之后,或許可以嘗試實現一下基于mysql的類似第三方包,這需要對mysql的一些機制搞得更加清楚才行。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://www.jianshu.com/p/c621f690123e

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 免费xxxxx大片在线观看影视 | 日本高清免费观看 | 亚洲精品国产一区二区第一页 | 唯美清纯 自拍偷 | 国产外围| 青青草原社区 | ass天天裸妇pics | 色先锋 影音先锋a 资源站 | 黑人巨大vs北条麻妃在线 | 精品国语对白精品自拍视 | 午夜福利在线观看6080 | 秋霞一级黄色片 | 视频在线免费看 | 日本人妖在线 | 日本在线视频免费观看 | 99热在线免费观看 | 色综合久久夜色精品国产 | 色综合视频一区二区三区 | 国产在线观看91精品一区 | 美女沟厕撒尿全过程高清图片 | 狠狠色综合久久久久尤物 | 春光乍泄在线 | 欧美亚洲天堂 | 水野朝阳厨房系列在线观看 | 亚洲va欧美va天堂v国产综合 | 日本漫画工囗全彩内番e绅 日本伦理动漫在线观看 | 色老大在线 | 午夜宅男在线观看 | 男人与禽交的方法 | 欧美极品brazzers 高清 | 99香蕉网| 韩国免费特一级毛片 | 色天天综合网色鬼综合 | 亚洲精品久久久WWW游戏好玩 | 精品湿| 国产小情侣自拍 | jm漫天堂破解版 | 福利片免费一区二区三区 | w7w7w7w7w免费 | 日本三级成人中文字幕乱码 | 王淑兰与铁柱全文免费阅读 |