Простой пример

Reconciliation в системах и финансах означает сверку данных между двумя источниками, чтобы убедиться, что они описывают одну и ту же реальность.

По-русски обычно говорят:

  • сверка;
  • взаимная сверка;
  • контроль соответствия;
  • сопоставление учётных данных.

Банк A считает:

Мы отправили банку B 100 переводов на сумму 1 000 000 рублей.

Банк B считает:

Мы получили 99 переводов на сумму 990 000 рублей.

Reconciliation должен обнаружить расхождение:

  • один перевод потерялся;
  • завис;
  • был отклонён;
  • пришёл повторно;
  • неправильно записан;
  • находится в промежуточном статусе.

То есть reconciliation отвечает на вопрос:

Совпадает ли то, что одна система считает произошедшим, с тем, что считает произошедшим другая система?


Зачем reconciliation нужен, если есть транзакции

Транзакция гарантирует согласованность внутри определённой границы.

Например, локальная транзакция базы данных может гарантировать:

создали payment
+
уменьшили баланс
+
записали ledger entry

Но она не может автоматически гарантировать, что:

  • внешний банк получил запрос;
  • платёжный провайдер обработал операцию;
  • Kafka-сообщение было корректно обработано;
  • деньги реально зачислены;
  • данные во второй независимой системе совпадают.

Особенно это важно в распределённых системах, где нет одной общей ACID-транзакции на все сервисы и организации.

Поэтому reconciliation является не заменой транзакциям, а вторым контуром контроля.

Транзакция:
не допустить ошибку внутри операции.

Reconciliation:
обнаружить ошибку, если системы всё-таки разошлись.

Пример в платёжной системе

Допустим, есть:

Payment Service
Bank Adapter
External Bank
Ledger
Settlement System

Payment Service записал:

payment_id = 123
status = SENT
amount = 10 000

Внешний банк записал:

external_reference = XYZ
status = REJECTED

Если callback от банка потерялся, внутренняя система продолжает считать платёж отправленным.

Reconciliation-процесс позже делает запрос или получает файл банка и видит:

Наша система: SENT
Банк: REJECTED

После этого система может:

  • изменить статус платежа;
  • вернуть деньги;
  • создать compensating transaction;
  • отправить событие;
  • создать инцидент;
  • передать случай оператору.

Как обычно работает reconciliation

1. Получение данных из двух источников

Например:

Источник A:
внутренняя база платежей

Источник B:
отчёт банка или API платёжного провайдера

Данные могут поступать:

  • через API;
  • через SFTP;
  • CSV-файлом;
  • банковским settlement-файлом;
  • из Kafka;
  • через database export;
  • через webhook;
  • через периодический polling.

2. Нормализация данных

У разных систем могут различаться:

  • форматы дат;
  • валюты;
  • идентификаторы;
  • названия статусов;
  • точность денежных значений;
  • часовые пояса.

Например:

Внутренняя система: SUCCESS
Внешняя система: SETTLED

Семантически это может быть одно состояние, хотя строки не совпадают.

Поэтому перед сравнением данные приводят к общей модели.


3. Matching

Необходимо понять, какие записи соответствуют друг другу.

Лучший вариант:

payment_id = payment_id

Но часто приходится сопоставлять по набору признаков:

external_reference
amount
currency
date
account
merchant

Например:

amount = 5000
currency = RUB
account = 1234
transaction_date = 15 июля

Это уже менее надёжный matching, потому что две одинаковые операции могут выглядеть одинаково.

Поэтому хороший системный дизайн предусматривает сквозной идентификатор операции.


4. Сравнение

Проверяются:

  • наличие записи с обеих сторон;
  • сумма;
  • валюта;
  • статус;
  • комиссия;
  • дата;
  • получатель;
  • количество операций;
  • итоговые агрегаты.

5. Классификация расхождений

Типичные категории:

Missing internally

Внешняя система знает об операции, внутренняя нет.

Банк: операция существует
Мы: операции нет

Missing externally

Внутренняя система считает, что операция отправлена, но внешняя её не видит.

Мы: SENT
Банк: not found

Status mismatch

Мы: SUCCESS
Банк: FAILED

Amount mismatch

Мы: 10 000
Банк: 9 900

Возможно, не была учтена комиссия.

Duplicate

Одна операция учтена дважды.

Timing difference

Операция ещё не дошла до финального состояния.

Мы: PROCESSING
Банк: пока отсутствует

Это не обязательно ошибка. Возможно, просто временной лаг.


Reconciliation бывает операционным и финансовым

Операционный reconciliation

Проверяет состояние отдельных операций.

Например:

Каждый payment_id должен иметь соответствующую запись у провайдера.

Вопрос:

Где именно потерялась или разошлась конкретная операция?

Финансовый reconciliation

Проверяет суммы и остатки.

Например:

Сумма всех успешных платежей:
10 000 000 рублей

Сумма settlement от банка:
9 980 000 рублей

Разница:
20 000 рублей

Здесь система ищет источник финансового расхождения.


Reconciliation и settlement

Эти понятия связаны, но не совпадают.

Settlement

Это фактический расчёт между сторонами.

Например:

Платёжный провайдер должен перечислить магазину 980 000 рублей после удержания комиссии.

Reconciliation

Это проверка:

Действительно ли обе стороны согласны, что должно быть перечислено именно 980 000 рублей?

То есть:

Reconciliation = сверили, что должны друг другу.
Settlement = фактически рассчитались.

Reconciliation в микросервисах

Термин используется не только в банковской сфере.

Допустим, есть:

Order Service
Payment Service
Inventory Service
Delivery Service

Order Service считает:

order = PAID

Payment Service считает:

payment = FAILED

Это нарушение межсервисного инварианта.

Reconciliation job может периодически искать такие комбинации:

order.status = 'PAID'
AND payment.status != 'SUCCESS'

После обнаружения система либо автоматически исправляет состояние, либо создаёт задачу оператору.


Reconciliation и Kubernetes

В Kubernetes reconciliation имеет близкий, но несколько другой смысл.

Контроллер постоянно сравнивает:

Desired state
с
Actual state

Например, желаемое состояние:

replicas: 3

Фактически работает:

2 pod

Reconciliation loop обнаруживает расхождение и создаёт третий pod.

Здесь reconciliation означает:

Привести фактическое состояние системы к заявленному желаемому состоянию.

Схема:

Desired state
      ↓
Сравнение
      ↓
Actual state
      ↓
Корректирующее действие

В финансовых системах reconciliation чаще сначала обнаруживает расхождение, а исправление может выполняться отдельным процессом.


Reconciliation job

Часто это периодическая задача:

каждые 15 минут
каждый час
раз в сутки
после получения settlement-файла

Например:

1. Взять все платежи за 15 июля.
2. Получить отчёт провайдера за 15 июля.
3. Сопоставить записи.
4. Найти расхождения.
5. Повторно проверить временные расхождения.
6. Автоматически исправить безопасные случаи.
7. Остальные отправить на manual review.

Важно, чтобы job была:

  • идемпотентной;
  • перезапускаемой;
  • наблюдаемой;
  • устойчивой к частично загруженным данным;
  • способной обрабатывать большие объёмы пакетами.

Что важно сказать на system design интервью

Можно сформулировать так:

Поскольку система взаимодействует с внешним банком, мы не можем обеспечить одну распределённую ACID-транзакцию между организациями. Поэтому кроме основного transactional flow я добавлю reconciliation-процесс. Он будет периодически сопоставлять внутренние операции с отчётами или API банка, находить missing, duplicate, amount mismatch и status mismatch операции и либо автоматически выполнять корректирующие действия, либо отправлять их на ручную обработку.

Это показывает, что ты понимаешь важную вещь:

Распределённая система не только предотвращает ошибки. Она должна уметь обнаруживать и исправлять уже возникшее расхождение.


Самая точная смысловая формула

Reconciliation =
систематическое сопоставление независимых представлений об одних событиях
для обнаружения и разрешения расхождений.

Независимость здесь принципиальна. Если две таблицы заполняются одним и тем же ошибочным кодом, их совпадение ещё ничего не доказывает. Сильный reconciliation сравнивает действительно разные контуры: например, внутренний ledger и внешний банковский settlement-отчёт.

Прокрутить вверх