国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

python實現(xiàn)redis三種cas事務(wù)操作

2020-02-16 11:10:27
字體:
供稿:網(wǎng)友

cas全稱是compare and set,是一種典型的事務(wù)操作。

簡單的說,事務(wù)就是為了存取數(shù)據(jù)庫中同一數(shù)據(jù)時不破壞操作的隔離性和原子性,從而保證數(shù)據(jù)的一致性。

一般數(shù)據(jù)庫,比如MySql是如何保證數(shù)據(jù)一致性的呢,主要是加鎖,悲觀鎖。比如在訪問數(shù)據(jù)庫某條數(shù)據(jù)的時候,會用SELECT FOR UPDATE ,這MySql就會對這條數(shù)據(jù)進行加鎖,直到事務(wù)被提交(COMMIT),或者回滾(ROLLBACK)。如果此時,有其他事務(wù)對被加鎖的數(shù)據(jù)進行寫入,那么該事務(wù)將會被阻塞,直到第一個事務(wù)完成為止。它的缺點在于:持有鎖的事務(wù)運行越慢,等待解鎖的事務(wù)阻塞時間就越長。并且容易產(chǎn)生死鎖(前面有篇文章有講解死鎖)!

本文會介紹三種redis實現(xiàn)cas事務(wù)的方法,并會解決下面的虛擬問題:
維護一個值,如果這個值小于當(dāng)前時間,則設(shè)置為當(dāng)前時間;如果這個值大于當(dāng)前時間,則設(shè)置為當(dāng)前時間+30。簡單的單線程環(huán)境下代碼如下:

# 初始化r = redis.Redis()if not r.exists("key_test"):  r.set("key_test", 0)def inc():  count = int(r.get('key_test')) + 30 #1  # 如果值比當(dāng)前時間小,則設(shè)置為當(dāng)前時間  count = max(count, int(time.time())) #2  r.set('key_test', count) #3  return count

很簡單的一段代碼,在單線程環(huán)境下可以跑的很歡,但顯然,是無法移植到多線程或者是多進程環(huán)境的(進程A和B同時運行到#1,獲取了相同的count值,然后運行#2#3,會導(dǎo)致count值總共只增加了30)。而為了能在多進程環(huán)境下運行,我們需要引入一些其他的東西。

py-redis本身自帶的事務(wù)操作

redis有這么幾個和事務(wù)相關(guān)的命令,multi,exec,watch。通過這幾個命令,可以實現(xiàn)‘將多個命令打包,然后一次性、按順序執(zhí)行,且不會被終端'。事務(wù)會從MULTI開始,執(zhí)行EXEC后觸發(fā)事件。另外,我們還需要WATCH,watch可以監(jiān)視任意數(shù)量的鍵,當(dāng)在調(diào)用EXEC執(zhí)行事務(wù)時,如果任意一個鍵被修改了,整個事務(wù)不會執(zhí)行。

下邊是使用redis本身的事務(wù)解決cas問題的代碼。

class CasNormal(object):  def __init__(self, host, key):    self.r = redis.Redis(host)    self.key = key    if not self.r.exists(self.key):      self.r.set(self.key, 0)  def inc(self):    with self.r.pipeline() as pipe:      while True:        try:          #監(jiān)視一個key,如果在執(zhí)行期間被修改了,會拋出WatchError          pipe.watch(self.key)          next_count = 30 + int(pipe.get(self.key))          pipe.multi()          if next_count < int(time.time()):            next_count = int(time.time())          pipe.set(self.key, next_count)          pipe.execute()          return next_count        except WatchError:          continue        finally:          pipe.reset()

代碼也不復(fù)雜,引入了之前說到的multi,exec,watch,如果對事務(wù)操作比較熟悉的同學(xué),可以很容易看出來,這是一個樂觀鎖的操作(咱們假設(shè)沒人競爭來著,每次去拿數(shù)據(jù)的時候都不會上鎖,真有人來改了再說。)樂觀鎖在高并發(fā)的情況下會顯得很無力,文末的性能對比會顯示這個問題。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 行唐县| 抚州市| 巴林左旗| 秦安县| 黔东| 山丹县| 绵阳市| 孝昌县| 上林县| 安龙县| 紫阳县| 祁阳县| 南陵县| 镇赉县| 边坝县| 阳谷县| 墨江| 建湖县| 施甸县| 诸暨市| 凤冈县| 虎林市| 耒阳市| 安岳县| 辽阳县| 黑水县| 高青县| 南乐县| 淮北市| 建阳市| 罗源县| 泉州市| 九龙坡区| 周至县| 泰和县| 崇信县| 霍城县| 鸡西市| 新疆| 万安县| 岳西县|