class ThreePhaseCommit:
def __init__(self):
self.state = 'idle'
self.participants = []
def can_commit(self):
"""阶段1: 询问参与者是否可以提交"""
self.state = 'can_commit'
for p in self.participants:
if not p.can_commit():
return False
return True
def pre_commit(self):
"""阶段2: 预提交"""
self.state = 'pre_commit'
for p in self.participants:
p.pre_commit()
def do_commit(self):
"""阶段3: 执行提交"""
self.state = 'do_commit'
for p in self.participants:
p.commit()
self.state = 'committed'
2.3 Paxos算法
python复制代码
class Proposer:
def __init__(self, proposer_id):
self.proposer_id = proposer_id
self.proposal_number = 0
def prepare(self, acceptors):
"""准备阶段"""
self.proposal_number += 1
promises = []
for acceptor in acceptors:
response = acceptor.promise(self.proposal_number)
if response:
promises.append(response)
if len(promises) >= (len(acceptors) // 2) + 1:
# 找到最高编号的接受值
highest_value = max(promises, key=lambda x: x[0])[1]
return highest_value
def accept(self, acceptors, value):
"""接受阶段"""
accepts = []
for acceptor in acceptors:
if acceptor.accept(self.proposal_number, value):
accepts.append(True)
return len(accepts) >= (len(acceptors) // 2) + 1
# 确保用户会话内的数据一致性
class SessionConsistency:
def __init__(self):
self.session_cache = {}
def get_data(self, user_id, key):
"""获取数据,优先从会话缓存获取"""
session_key = f"{user_id}:{key}"
if session_key in self.session_cache:
return self.session_cache[session_key]
# 从数据库获取
data = db.query(f'SELECT * FROM data WHERE user_id = {user_id}')
# 更新会话缓存
self.session_cache[session_key] = data
return data
def update_data(self, user_id, key, value):
"""更新数据,同时更新会话缓存"""
session_key = f"{user_id}:{key}"
# 更新数据库
db.execute(f'UPDATE data SET value = {value} WHERE user_id = {user_id}')
# 更新会话缓存
self.session_cache[session_key] = value
五、分布式锁
5.1 Redis分布式锁
python复制代码
def acquire_lock(lock_name, timeout=10):
"""获取分布式锁"""
identifier = str(uuid.uuid4())
end = time.time() + timeout
while time.time() < end:
# SET NX(不存在时设置)+ EX(过期时间)
if redis_client.set(lock_name, identifier, nx=True, ex=timeout):
return identifier
time.sleep(0.01)
return None
def release_lock(lock_name, identifier):
"""释放分布式锁"""
# 使用Lua脚本保证原子性
script = """
if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
else
return 0
end
"""
redis_client.eval(script, 1, lock_name, identifier)
5.2 ZooKeeper分布式锁
python复制代码
from kazoo.client import KazooClient
class ZookeeperLock:
def __init__(self, zk_hosts):
self.zk = KazooClient(hosts=zk_hosts)
self.zk.start()
def acquire(self, lock_path):
"""获取锁"""
# 创建临时有序节点
node = self.zk.create(
f"{lock_path}/lock-",
b'',
ephemeral=True,
sequence=True
)
# 获取所有子节点
children = self.zk.get_children(lock_path)
children.sort()
# 检查是否是最小节点
if node == f"{lock_path}/{children[0]}":
return True
# 监听前一个节点
prev_node = f"{lock_path}/{children[children.index(node.split('/')[-1]) - 1]}"
event = threading.Event()
@self.zk.DataWatch(prev_node)
def watch(data, stat):
if stat is None:
event.set()
event.wait()
return True
def release(self, lock_path):
"""释放锁"""
# 删除节点
self.zk.delete(f"{lock_path}/lock-*")