Python Redis pipeline操作(秒杀实现)
設(shè)想這樣的一個(gè)場(chǎng)景,你要批量的執(zhí)行一系列redis命令,例如執(zhí)行100次get key,這時(shí)你要向redis請(qǐng)求100次+獲取響應(yīng)100次。如果能一次性將100個(gè)請(qǐng)求提交給redis server,執(zhí)行完成之后批量的獲取相應(yīng),只需要向redis請(qǐng)求1次,然后批量執(zhí)行完命令,一次性結(jié)果,性能是不是會(huì)好很多呢?
答案是肯定的,節(jié)約的時(shí)間是客戶端client和服務(wù)器redis server之間往返網(wǎng)絡(luò)延遲的時(shí)間。這個(gè)時(shí)間可以用ping命令查看。
網(wǎng)絡(luò)延遲高:批量執(zhí)行,性能提升明顯
網(wǎng)絡(luò)延遲低(本機(jī)):批量執(zhí)行,性能提升不明顯
某些客戶端(java和python)提供了一種叫做pipeline的編程模式用來解決批量提交請(qǐng)求的方式。
這里我們用python客戶端來舉例說明一下。
?
1、pipeline
網(wǎng)絡(luò)延遲
client與server機(jī)器之間網(wǎng)絡(luò)延遲如下,大約是30ms。
?
測(cè)試用例
分別執(zhí)行其中的try_pipeline和without_pipeline統(tǒng)計(jì)處理時(shí)間。?
# -*- coding:utf-8 -*-import redis import time from concurrent.futures import ProcessPoolExecutorr = redis.Redis(host='10.93.84.53', port=6379, password='bigdata123')def try_pipeline():start = time.time()with r.pipeline(transaction=False) as p:p.sadd('seta', 1).sadd('seta', 2).srem('seta', 2).lpush('lista', 1).lrange('lista', 0, -1)p.execute()print time.time() - startdef without_pipeline():start = time.time()r.sadd('seta', 1)r.sadd('seta', 2)r.srem('seta', 2)r.lpush('lista', 1)r.lrange('lista', 0, -1)print time.time() - startdef worker():while True:try_pipeline()with ProcessPoolExecutor(max_workers=12) as pool:for _ in range(10):pool.submit(worker)結(jié)果分析
try_pipeline平均處理時(shí)間:0.04659
without_pipeline平均處理時(shí)間:0.16672
我們的批量里有5個(gè)操作,在處理時(shí)間維度上性能提升了4倍!
網(wǎng)絡(luò)延遲大約是30ms,不使用批量的情況下,網(wǎng)絡(luò)上的時(shí)間損耗就有0.15s(30ms*5)以上。而pipeline批量操作只進(jìn)行一次網(wǎng)絡(luò)往返,所以延遲只有0.03s??梢钥吹焦?jié)省的時(shí)間基本都是網(wǎng)路延遲。
?
2、pipeline與transation
pipeline不僅僅用來批量的提交命令,還用來實(shí)現(xiàn)事務(wù)transation。
這里對(duì)redis事務(wù)的討論不會(huì)太多,只是給出一個(gè)demo。詳細(xì)的描述你可以參見這篇博客。redis事務(wù)
細(xì)心的你可能發(fā)現(xiàn)了,使用transaction與否不同之處在與創(chuàng)建pipeline實(shí)例的時(shí)候,transaction是否打開,默認(rèn)是打開的。
# -*- coding:utf-8 -*-import redis from redis import WatchError from concurrent.futures import ProcessPoolExecutorr = redis.Redis(host='127.0.0.1', port=6379)# 減庫(kù)存函數(shù), 循環(huán)直到減庫(kù)存完成 # 庫(kù)存充足, 減庫(kù)存成功, 返回True # 庫(kù)存不足, 減庫(kù)存失敗, 返回False def decr_stock():# python中redis事務(wù)是通過pipeline的封裝實(shí)現(xiàn)的with r.pipeline() as pipe:while True:try:# watch庫(kù)存鍵, multi后如果該key被其他客戶端改變, 事務(wù)操作會(huì)拋出WatchError異常pipe.watch('stock:count')count = int(pipe.get('stock:count'))if count > 0: # 有庫(kù)存# 事務(wù)開始pipe.multi()pipe.decr('stock:count')# 把命令推送過去# execute返回命令執(zhí)行結(jié)果列表, 這里只有一個(gè)decr返回當(dāng)前值print pipe.execute()[0]return Trueelse:return Falseexcept WatchError, ex:# 打印WatchError異常, 觀察被watch鎖住的情況print expipe.unwatch()def worker():while True:# 沒有庫(kù)存就退出if not decr_stock():break# 實(shí)驗(yàn)開始 # 設(shè)置庫(kù)存為100 r.set("stock:count", 100)# 多進(jìn)程模擬多個(gè)客戶端提交 with ProcessPoolExecutor(max_workers=2) as pool:for _ in range(10):pool.submit(worker) posted on 2018-11-28 11:01 _潛行者 閱讀(...) 評(píng)論(...) 編輯 收藏轉(zhuǎn)載于:https://www.cnblogs.com/wangwei916797941/p/10030882.html
總結(jié)
以上是生活随笔為你收集整理的Python Redis pipeline操作(秒杀实现)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中国企业云计算应用现状及需求
- 下一篇: vuescroll使用文档