前言
在建設數據庫高可用的時候,採用了consul的機制實現,在開發相關組件的時候,使用了consul的鎖機制。但是由於使用的不正確,帶來了一些問題,下面主要介紹我的使用場景及使用方式,出現的問題,以及正確的使用方法。
我的使用場景及使用方式簡介
在進行數據庫高可用的選舉組件設計時,考慮使用consul的鎖來進行consul-server的選舉,誰先獲取到鎖,誰就成爲consul-server的leader,由leader實施數據庫選主。
組件開發選用python進行開發,consul驅動使用的是python的consul驅動:【https://pypi.org/project/python-consul/】
驅動對於consul的相關操作基本與consul提供的api功能保持一致。
設計中每一套高可用服務都有一個鎖k-v,選舉動作觸發的時候,所有consul-server都會嘗試對這個鎖k-v加鎖,綁定自己的session id,完成選主動作後,再釋放鎖,即:
import consul
lock_key = "app1/master1/lock_key"
CONSUL_CLI = consul.Consul()
sid = CONSUL_CLI.session.create()
lock_flag = CONSUL_CLI.kv.put(lock_key, "test1-acquire", acquire=sid)
"""
選舉...
"""
CONSUL_CLI.session.destroy(sid)
存在的問題
當高可用服務中,假設架構爲
A:主
B:從1
C:從2
連續兩個節點A、B故障,此時應該由A切換到B,然後由B切換到C。
但是實際發生的時候,由A切換到B,但是B無法切換到C。
根據分析和測試,發現consul的鎖有兩個點沒注意到:
1、consul的鎖在非正常釋放的時候,會根據session的lock_delay參數進行解鎖延遲,這個lock_delay默認是15s。
2、通過destroy session的方式釋放鎖是非正常的鎖釋放,需要通過release操作纔是正確的鎖釋放。
根據這兩個點,基本上能確定,爲什麼A切換到B後,無法切換到C。
主要是A、B連續故障,選舉間隔在15s內,而程序是通過destroy session來釋放鎖,會有15s的鎖釋放延遲,導致B故障的時候consul-server無法獲取到鎖,從而無法進行選主,也就無法切換到C節點了。
正確的使用
根據以上兩點,做了兩點調整
1、通過release方式釋放鎖,使得鎖能夠正確釋放;
2、將lock_delay調成2s,避免非正常釋放鎖的情況下其他consul-server無法獲取到鎖,從而無法選舉出正確的主節點;
demo
import consul
lock_key = "app1/master1/lock_key"
CONSUL_CLI = consul.Consul()
sid = CONSUL_CLI.session.create(lock_delay=2)
lock_flag = CONSUL_CLI.kv.put(lock_key, "test1-acquire", acquire=sid)
"""
選舉...
"""
lock_flag = CONSUL_CLI.kv.put(lock_key, "test1-release", release=sid)
CONSUL_CLI.session.destroy(sid)