公告:文章會第一時間發在微信公衆號《魔笛手CTO》,歡迎關注
WEB服務,尤其是分佈式的WEB服務,通常會面臨需要實現安全高效的全局鎖的服務場景。而redis的諸多特性,使得藉助其實現的全局鎖顯得如此簡單。本篇文章藉助小明應聘魔笛手研發崗位的面試,層層遞進的來介紹一下如何通過redis實現全局鎖。
面試官老張:看你簡歷上說,之前的項目中使用了redis,你知道redis爲什麼是單線程的嗎?
小明:多進程或者多線程更多的爲了高效利用CPU,但是卻對開發人員提出了更高的要求。而redis作爲內存型數據庫,其性能瓶頸往往不是CPU,而是內存和網絡。單線程對於redis來說已經足夠快了,也就沒有必要再引入複雜的多任務模型。
注:官方文檔有提到單線程的redis就可以達到10W的QPS。
面試官老張:不錯,我再問一個簡單的問題,通過什麼命令爲一個key指定字符串的值。
小明:set命令。
面試官老張:恩,這個問題有點太簡單了哈,那你能介紹一下set命令都可以接收什麼參數嗎?
小明:這個我有查閱過,redis的set命令除了指定key和value,還有幾個可選參數,分別是:
- ex——設置key多少秒之後過期
- px——設置key多少毫秒之後過期
- nx——只有key不存在時,set操作纔會生效
- xx——只有key存在時,set操作纔會生效
面試官老張:很好,那你可以利用redis實現一把全局鎖嗎?
小明:那我通過python代碼來簡單實現一下吧。
from redis import Redis
LOCK_KEY = "global_lock"
AUTO_RELEASE_SECOND = 100
redis = Redis()
def acquire_lock():
if redis.set(LOCK_KEY, "1", nx=True, ex=AUTO_RELEASE_SECOND):
return True
return False
def release_lock():
redis.delete(LOCK_KEY)
利用nx參數,可以保證只有key不存在時纔會設置生效,這樣就併發操作中只有一個實例可以獲取生效狀態。
通過ex設置過期時間,可以保證獲取鎖的實例不會因爲崩潰或者忘記釋放,導致所有實例都無法獲取鎖。
注:覺得不過癮的同學可以看一下redis-py中關於Lock的實現。
面試官老張:非常好。今天的面試就到這吧。