本文目录导读:

保证Python脚本多次同步结果一致,核心问题是确定性和幂等性,以下是几种常见的场景和解决方案:
文件/数据同步的幂等性
使用哈希校验
import hashlib
import os
def get_file_hash(filepath):
"""计算文件哈希值"""
sha256_hash = hashlib.sha256()
with open(filepath, "rb") as f:
for byte_block in iter(lambda: f.read(4096), b""):
sha256_hash.update(byte_block)
return sha256_hash.hexdigest()
def sync_file(src, dst):
"""幂等文件同步"""
# 检查目标是否存在且内容相同
if os.path.exists(dst):
if get_file_hash(src) == get_file_hash(dst):
print(f"文件已同步: {dst}")
return True
# 执行同步
with open(src, 'rb') as f_src:
with open(dst, 'wb') as f_dst:
f_dst.write(f_src.read())
# 验证同步结果
assert get_file_hash(src) == get_file_hash(dst)
print(f"同步完成: {dst}")
return True
使用版本号或时间戳
import json
import os
class SyncTracker:
def __init__(self, state_file="sync_state.json"):
self.state_file = state_file
self.state = self.load_state()
def load_state(self):
"""加载同步状态"""
if os.path.exists(self.state_file):
with open(self.state_file, 'r') as f:
return json.load(f)
return {}
def save_state(self):
"""保存同步状态"""
with open(self.state_file, 'w') as f:
json.dump(self.state, f, indent=2)
def need_sync(self, item_id, item_version):
"""检查是否需要同步"""
if item_id not in self.state:
return True
return self.state[item_id] != item_version
def mark_synced(self, item_id, item_version):
"""标记已同步"""
self.state[item_id] = item_version
self.save_state()
数据库同步的一致性
使用事务和唯一约束
import sqlite3
class DatabaseSync:
def __init__(self, db_path):
self.db_path = db_path
self.init_db()
def init_db(self):
"""初始化数据库结构"""
with sqlite3.connect(self.db_path) as conn:
conn.execute("""
CREATE TABLE IF NOT EXISTS sync_items (
id TEXT PRIMARY KEY,
data TEXT NOT NULL,
version INTEGER NOT NULL,
sync_timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
def upsert_item(self, item_id, data, version):
"""幂等插入或更新"""
with sqlite3.connect(self.db_path) as conn:
conn.execute("""
INSERT OR REPLACE INTO sync_items (id, data, version)
VALUES (?, ?, ?)
WHERE id NOT IN (
SELECT id FROM sync_items WHERE version >= ?
)
""", (item_id, data, version, version))
def get_sync_status(self):
"""获取同步状态"""
with sqlite3.connect(self.db_path) as conn:
cursor = conn.execute("""
SELECT id, version FROM sync_items
""")
return dict(cursor.fetchall())
API数据同步的一致性
使用轮询和去重
import requests
import json
from datetime import datetime
class APISyncClient:
def __init__(self, api_url, last_sync_file="last_sync.json"):
self.api_url = api_url
self.last_sync_file = last_sync_file
self.processed_ids = set()
def load_last_sync(self):
"""加载上次同步状态"""
try:
with open(self.last_sync_file, 'r') as f:
return json.load(f)
except FileNotFoundError:
return {"last_timestamp": None, "processed_ids": []}
def save_last_sync(self, timestamp, processed_ids):
"""保存同步状态"""
state = {
"last_timestamp": timestamp,
"processed_ids": list(processed_ids)
}
with open(self.last_sync_file, 'w') as f:
json.dump(state, f)
def sync_data(self):
"""同步API数据"""
state = self.load_last_sync()
self.processed_ids = set(state.get("processed_ids", []))
last_timestamp = state.get("last_timestamp")
if last_timestamp:
params = {"since": last_timestamp}
else:
params = {}
response = requests.get(self.api_url, params=params)
data = response.json()
new_ids = set()
for item in data.get("items", []):
item_id = item["id"]
# 去重检查
if item_id in self.processed_ids:
continue
# 处理数据
self.process_item(item)
new_ids.add(item_id)
# 更新状态
current_timestamp = datetime.now().isoformat()
self.processed_ids.update(new_ids)
self.save_last_sync(current_timestamp, self.processed_ids)
def process_item(self, item):
"""处理单个数据项"""
# 实现数据处理逻辑
print(f"Processing: {item}")
分布式锁确保一致性
import threading
import time
from functools import wraps
class DistributedLock:
def __init__(self):
self.lock = threading.Lock()
self.operation_log = []
def synchronized(self, func):
@wraps(func)
def wrapper(*args, **kwargs):
with self.lock:
operation_id = f"{func.__name__}_{time.time()}"
# 检查是否已执行过
if operation_id in self.operation_log:
print(f"操作 {operation_id} 已执行,跳过")
return None
result = func(*args, **kwargs)
self.operation_log.append(operation_id)
return result
return wrapper
# 使用示例
lock = DistributedLock()
@lock.synchronized
def critical_sync_operation():
"""关键同步操作"""
time.sleep(1) # 模拟耗时操作
return "Operation completed"
# 多次调用,只有第一次会实际执行
critical_sync_operation()
critical_sync_operation() # 跳过
最佳实践总结
状态管理
class SyncManager:
"""统一的同步管理器"""
def __init__(self):
self.sync_state = {}
self.lock = threading.Lock()
def try_sync(self, item_id, sync_func):
"""尝试同步,返回是否成功执行"""
with self.lock:
if item_id in self.sync_state:
print(f"跳过已同步项: {item_id}")
return False
try:
sync_func()
self.sync_state[item_id] = True
return True
except Exception as e:
print(f"同步失败: {e}")
return False
关键原则
- 使用唯一标识符:每个同步项应有唯一ID
- 保存同步状态:记录已同步的ID和时间戳
- 实现幂等操作:相同操作多次执行结果相同
- 添加版本控制:避免旧数据覆盖新数据
- 使用事务:确保操作的原子性
- 校验机制:同步后验证数据一致性
这些方法可以组合使用,根据具体场景选择合适的策略,关键在于追踪状态和避免重复操作。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播