Python脚本如何保证多次同步结果一致

wen python案例 36

本文目录导读:

Python脚本如何保证多次同步结果一致

  1. 文件/数据同步的幂等性
  2. 数据库同步的一致性
  3. API数据同步的一致性
  4. 分布式锁确保一致性
  5. 最佳实践总结

保证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

关键原则

  1. 使用唯一标识符:每个同步项应有唯一ID
  2. 保存同步状态:记录已同步的ID和时间戳
  3. 实现幂等操作:相同操作多次执行结果相同
  4. 添加版本控制:避免旧数据覆盖新数据
  5. 使用事务:确保操作的原子性
  6. 校验机制:同步后验证数据一致性

这些方法可以组合使用,根据具体场景选择合适的策略,关键在于追踪状态避免重复操作

抱歉,评论功能暂时关闭!