> Как решить проблему повторного запроса при переводе денег, чтобы избежать двойного списания? (Python)
Уровень: senior · Роль: backend · Язык: Python · Категория: Технические вопросы
Компании: HeadHunter
Стек: Python
> Пример ответа
Для решения проблемы повторного запроса при переводе денег и предотвращения двойного списания используется идемпотентность. Основной подход - внедрение ключа идемпотентности (Idempotency Key) на стороне клиента или сервера.
Пример реализации на Python:
- Генерация и передача ключа: Клиент отправляет уникальный
idempotency_key(например, UUID) в заголовке запроса. - Проверка на сервере: Сервер проверяет, был ли уже обработан запрос с таким ключом. Если да - возвращает предыдущий результат, не выполняя операцию повторно.
- Атомарность: Используйте транзакции базы данных с блокировкой или атомарные операции (например,
INSERT ... ON CONFLICT DO NOTHINGв PostgreSQL).
PYTHONimport uuidfrom flask import Flask, request, jsonifyfrom your_db import db # гипотетическая БДapp = Flask(__name__)@app.route('/transfer', methods=['POST'])def transfer_money():idempotency_key = request.headers.get('Idempotency-Key')if not idempotency_key:return jsonify({'error': 'Missing idempotency key'}), 400# Проверяем, был ли уже обработан запросexisting = db.fetch_one("SELECT status FROM transfers WHERE idempotency_key = %s",(idempotency_key,))if existing:return jsonify({'status': existing['status']}), 200# Начинаем транзакциюtry:# Резервируем ключ атомарно (например, вставляем запись с уникальным ключом)db.execute("INSERT INTO transfers (idempotency_key, status) VALUES (%s, 'pending')",(idempotency_key,))# Выполняем перевод (списание и зачисление)# ... логика перевода ...db.execute("UPDATE transfers SET status = 'completed' WHERE idempotency_key = %s",(idempotency_key,))db.commit()return jsonify({'status': 'completed'}), 200except IntegrityError: # дубликат ключаdb.rollback()return jsonify({'status': 'already_processing'}), 409
Дополнительные меры:
- Используйте распределённые блокировки (например, Redis) для критических секций.
- Установите TTL для ключей идемпотентности (например, 24 часа).
- Логируйте все запросы для аудита.
Этот подход гарантирует, что даже при повторной отправке запроса (из-за таймаута или сбоя сети) списание произойдёт только один раз.
> Похожие задачи по Python
Как решить проблему гонки при переводе денег между счетами?
Помогает ли транзакция с уровнем изоляции сериализации при race condition?
Что можно сделать для увеличения стабильности сетевых запросов?
Какова иерархия процессов, потоков и asyncio в Python?
> Похожие задачи по backend
Как решить проблему гонки при переводе денег между счетами?
Помогает ли транзакция с уровнем изоляции сериализации при race condition?
Что можно сделать для увеличения стабильности сетевых запросов?
Какова иерархия процессов, потоков и asyncio в Python?
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью