Pull to refresh

Comments 38

А в чем, собственно, заключается "обработка платежа"? Проверка баланса и сохранение транзакции?

Обработка платежа - это создать все необходимые записи, если их можно создать, ведь средств может не хватать, а затем завершить или отменить.


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

В рамках сервиса Баланс возможно агрегирование нескольких списаний с одной сущности баланс, а так же наоборот разделение списания между разными сущностями баланс, когда не хватает средств.

Приведу пример:

Вам нужно оплатить покупку билета в метро, скажем 50 рублей. Но у вас есть 20 рублей обычных и 30 рублей только для оплаты метро. В итоге ваше списание 50 рублей создаст 2 транзакции, хотя для вас это платеж один, продавец при этом получит ваши 20 обычных рублей и 30 специальных рублей, что он с ними будет делать - это отдельный разговор.

Пример 2:

Вы заказали пиццу (900р) и желаете сразу оплатить чаевые курьеру (100р), хотя система отправит 900р и 100р тем, кто их должен получить, с вашего баланса, на котором есть 1000 рублей, будет списано 1000 рублей и создано 2 транзакции, описывающие причину списания (одна на оплату пиццы, вторая на перевод чаевых).

(Это то, как сейчас работает сервис Баланс)

А можно сделать так: в обоих случаях вместо кучи 1-1 транзакций создаётся одна м-м, в которой записано сколько с каких счетов идёт списание и сколько куда начисление. А баланс счёта определяется разницей между всеми начислениями и всеми списаниям.

Это работает только при условиях:
1. Система не распределенная;
2. Все балансы одинаковые.

В сервисе Баланс все сущности типа баланс на данный момент величины векторные, приведу пример, есть рублевый баланс, но на них есть метка "Не для перевода заграницу", так же у вас есть рублевый баланс без ограничений, запишем их как (рубль,["Не для перевода заграницу"]) и (рубль,[]) соответственно. Эти балансы разные и их нельзя смешивать, это как разные типы. При попытке снять средства для оплаты зарубежной покупки - рубли с первого баланса недоступны.

Так же нужно учитывать, что сервис Баланс списывает деньги вникуда и зачисляет деньги изниоткуда. Куда уйдут деньги - решает сервис контрактов. Поэтому так важно, что бы сервис Баланс сообщил точно, какой тип средств он списал. Потому что разница между (рубль,["Не для перевода заграницу"]) и (рубль,[]) существенна.

В будущем, эта фича может быть использована для локализации денег в определенном контуре экономики государства. Например выдается кредит, льготный, фермеру на покупку оборудования, гсм и семян и только у отечесвенного производителя. На эти деньги он ничего кроме этих категорий купить не может. Он даже положить их на депозит не сможет, потому что это тоже "покупка", просто покупаешь в этом случае долг с типом "депозит".
Когда эти деньги получит отечественный производитель, то он с ними идет "куда-то", где ему эти деньги меняют на что-то, что было обговорено заранее в рамках программы, все же такие вещи не делаются персонально под одного фермера.

В приведенном вами примере идет настолько существенное упрощение, что работать это будет только если есть некая центральная СУБД, куда все стекается, у каждого в ней есть счет и в итоге получаем ЦБ дубль 2. Не надо так.

А зачем вы счета балансами называете? Я бы не стал пользоваться сервисом, который списывает деньги "вникуда" и эмитит их "изниоткуда". Каким образом вы собираетесь проверять положительность баланса без "центральной субд, куда всё стекается", я бы послушал.

Счет - это совокупность балансов. У вас на счету может быть множество валют одновременно и при этом эти валюты сами могут быть типизированными, как ранее описывал.

Сервис контрактов следит за тем, что бы, если 100 рублей списали у Васи, то эти 100 рублей обязательно у кого-то оказались.
Контракт не завершится, если сальдо с бульбой не сойдется. У кого-то -100, у кого-то +100. Иначе никак. Причем с соблюдением типа.

Сервис Баланс сделан целенаправленно именно таким, что работает с конкретным счетом и говорит о том, что он конкретно может по запросу сделать.

Приведу пример развернуто из того, что было выше:

Что бы перевести 100 рублей от Васи к Пете - сервис контрактов в начале попытается создать платеж у Васи, когда сервис Баланс скажет, что создал списание на 100 обычных рублей под идентификатором запроса Списание1, то сервис контрактов отправит запрос за зачисление 100 рублей Пете (мы не можем сразу же формировать зачисление, потому что не знаем вектор типа перечисляемых Пете рублей, у Васи могут быть маркированные рубли же, причем сам Вася о том, что его рубли меченные никогда не узнает, в будущем будет статья про СОРМ). Если сервис Баланс опять сообщит, что зачислить могу и жду подтверждения по идентификатору Зачисление1, тогда контракт переходит в стадию "Завершение". В этой стадии он уже не может быть отменен никем, даже системой, и отправляются подтверждения созданных ранее Списание1 и Зачисление1. В этот момент Петя получает свои деньги, а Вася получить обратно свои деньги уже не сможет, потому что контракты не отменяются и удалить их нельзя.
Если он отправил деньги Пете по ошибке, то нужно создавать контракт на обратный перевод.

А теперь представь себе, что Вася живет в Москве, а Петя в Рио - о какой централизованной БД может идти речь?

Деньги в системе никуда не пропадают.
Сервис Баланс - это подсистема большой системы и сами валюты - это один из ресурсов, которыми оперирует подсистема контрактов.

Вся платежная система строилась исходя из того, что будут центры в каждой области, плотность расположения узлов - в соответствии с нуждами экономики. Нет никакой централизации в проведении платежей у системы и она не нужна.

Вы не в курсе, что в номере счета зашит код валюты?

Еще раз повторяю. ЦБ и банки - это анахронизм и его давно пора убирать. Те государства, которые это своевременно не поймут - уйдут в историю.
В mireapay ничего в номер счета не зашито и нет смысла этого делать.

Вы пытаетесь разговаривать со мной с точки зрения текущей инфраструктуры, которую автор и ставит своей целью упразднить и убрать.

И да, у меня есть способ, как мигрировать на новую инфраструктуру. Это не быстрый процесс, но реальный.

Так же вы видимо забываете, что у меня нет заказчика и нет требований от него, что я обязан следовать требованиям "какого-то там регулятора с горы".

Что бы что-то требовать от меня, нужно для начала иметь влияние. А писать про "у нас оно работать так должно" - идите к тем, кто сидит на зарплате.

Если вы не способны мыслить за рамками вашего "загона", то пожалуйста, не тратьте хотя бы собственное время. Я уверен, что вы очень занятой человек, занимающий важную должность "где-то".

Этот разговор не стоит затрачиваемого вами времени.

Ох уж эти оторванные от жизни мечтатели. Как текущая система работает и почему именно так разбираться не стали. Даже в терминах поленились разобраться. Зато фантазируют о прекрасном будущем, где национальная валюта не будет контролироваться государством, налоговой плевать на отчётность, а мошенников не то что ловить не будут, а даже наоборот будут помогать, создавая децентрализованные миксеры.

  1. У налоговой в системе mireapay контроль еще выше, чем в текущей системе. Налоговая буквально является частью платежной системы и все проводимые платежи по идее должны проводиться с уплатой налогов сразу в налоговую, минуя всякие юрлица, т.е. покупая что-то - НДС сразу улетает в налоговую, переводя зп сотруднику - НДФЛ сразу вычисляется системой;

  2. Контроль у государства в mireapay еще выше, чем есть сейчас, потому что можно не только контроллировать куда уходят деньги, но и кому и почему. Этому будет посвящена отдельная статья про СОРМ и в целом гос безопасность с секретностью;

  3. Мошенникам будет еще сложнее, потому что если физ лицо получает деньги от множества других лиц (или сумма слишком большая, скажем больше 100 тыс), то полученные деньги могут быть "временно" заморожены и доложено куда надо, что бы разобрались. Деньги будут на счету у "мошенника", но забрать их можно будет в любой момент и вернуть потерпевшему, пока заморозка конкретных средств не пройдет. Причем работает это таким образом, что замораживается конкретная сумма, а не вообще весь счет. Даже если будет ложное срабатывание - людям жизнь это не испортит, свои деньги, которые у него до этого были - он сможет тратить как и раньше.

Уважаемый, правда, я вижу что вам в боль со мной общаться и вам сложно понять мои слова. Вы не читали мои статьи, особенно от 1 сентября, где все описано.
Перечитайте, пожалуйста, мои статьи по mireapay. Вам яснее станет, что никаких мечтательством у меня и не пахнет в работе.

А давайте вы сперва научитесь пользоваться гиперссылками. Вашей статье определённо не хватает какого-то контекста, который есть исключительно в вашей голове. Снимите корону с головы и примите тот факт, что никто тут не следит за вашим творчеством.

:-) А как быть с блокировками и параллельностью при такой бизнес логике работы?
Есть один "Общий баланс" с минимально допустимым значением на который влияют операции по всем "Частным балансам".
Операция проверяет "Общий баланс" и если он "допустим", проверяет "Частный баланс", и если он больше суммы операции его уменьшает, после уменьшения "Частного баланса" необходимо уменьшить (на сумму операции) "Общий баланс". На все это у вас есть пара секунд до "ответа" - успешно операция выполнилась или нет.
И как предлагаете обойтись без транзакций и блокировок если у вас миллионы "Частных счетов" и тысяча операций в секунду? :-)

Сущность баланс всегда принадлежит конкретному пользователю, на нее не может быть 1000рпс, да и количество обращений значения не имеет на самом деле. Больше сказать не могу, т.к. хочу, что бы вы сделали самостоятельно домашнее задание.
Если что, мне ваш код не нужен - и сам напишу =)

Видимо понятия "Консолидированный баланс" для вас не существует? :-)
Тогда "для простоты", пусть "баланс всегда принадлежит конкретному пользователю" но есть условие проверки, что общая сумма "по 1000рпс" (десятка миллионов пользователей) за сутки (ну или за час) не должна превысить определенной конкретной величины.... :-)

Когда происходит создание платежа - средства резервируются. Они находятся на балансе, но другие процессы их получить не могут. Это то, как работает сервис Баланс сейчас и то, как он должен работать после выполнения домашнего задания.

Про бухгалтерскую терминологию ничего не знаю.

Если на пальцах:

У вас есть 1000 рублей. Если одновременно будет 11 списаний по 100 рублей, то 10 из них сообщат, что списать могут и ждут команду на подтверждение или отмену, и 11 скажет, что денег нет, но вы держитесь. Какой конкретно платеж будет одинадцатым - определить нельзя, любой из 11, при условии, что создавались одновременно.

Блокировки записей тут не происходит, блокируются значения, сами средства, поэтому и есть возможность не использовать транзакции БД или блокировку записей.

Еще раз... Для непонятливых.... Внешняя от вашей логики система не ждет от вас ответа - "что списать могут и ждут команду на подтверждение или отмену"...
А ждет от вас однозначный ответ "да" или "нет" за ограниченное количество времени (банкомат ждет выдать вам денег или нет...).

Банкомат работает с сервисом контрактов, а не с отдельными компонентами платежной системы.

Вы же, что бы получить деньги в банке (представляете, так можно, прийти в кассу и снять деньги) - не идете к инкасатору с документами вместо кассира, что бы он вам отсыпал денег?

Банкомат тупо от управляющей системы (на свой запрос) ждет ответа - выдавать ему деньги или нет. А вот логика управляющей системы свой ответ предоставляет в зависимости от бизнес логики, которая (в свою очередь) проверяет кучу условий по тому запросу который пришел от банкомата. Одно из бизнес условий я вам озвучил - до проверки клиентского контракта необходимо проверить другой контракт (в условия/баланс которого входят миллионы клиентских). Так как решать то такую проблему?
30 лет назад когда большинство контрактов (и клиентские и консолидированные) были кредитные (не контролирующие в момент исполнения Online операции балансы), проблема не возникала, но... Времена и бизнес условия с тех пор изменились значительно...

Банкомат - это просто "еще один кошелек", что бы выдать деньги мы можем передавать деньги на кошелек банкомата. Если успешно проходит - выдаем деньги. Тот кто стоит перед банкоматом деньги не получит, если у него на балансе нет нужной суммы и/или у банкомата нет нужных средств для выдачи - например не хватает банкнот или еще какой-либо мелочи. Причем при формировании таких запросов можно контроллировать такую штуку как "банкнотный ресурс" - потому что банкноты не являются "деньгами", это штуки, у которых есть серийник и от продажи чайников они никак не отличаются. Человек, который в банкомате снимает деньги для системы mireapay будет выглядеть как покупать банкнот с номерами 1,2,3,4. И это будет отражаться в контракте. Правда скорее всего для этого уже нужно будет банкоматы переделывать. Вряд ли серийники где-то хранятся в банкоматах сейчас и/или есть возможность у инкасаторов вводить такую информацию.

И это лишь один из вариантов решения. Если вас для принципиально, что банкомат - это тупая кнопка, то можно списывать деньги со счета клиента на какой-нибудь специальный счет. И потом система уже выдаст разрешение, что выдать деньги можно.

Но первый вариант мне кажется намного лучше, потому что у каждого банкомата будет свой цикл обработки и все что ему нужно будет - это дождаться завершения обработки контракта - считай разрешения, что можно выдать деньги или нет. Я уже не говорю про безопасность и аудит. На счете банкомата должен отражатся объем выданных средств. При начислении денег (клиент вносит сумму в банкомат) - банкомат переводит со своего счета на счет клиента - т.е. в явной форме еще и фиксируется откуда пришли деньги, потому что у каждого банкомата свой счет. Можно проводить аудит конкретного банкомата. Если удается - он завершает операцию, если нет - возвращает деньги. Если деньги вносит инкасатор - то деньги списываются в специальный счет - печатную машинку откуда деньги могут генерироваться в систему и который их и поглощает, цифры на этом счете можно рисовать любые, потому что это делает государство и ему без разницы какая сумма там будет, потому что эти деньги не существуют для экономики. Так как вся система контроллируется гос органами и только государство владеет узлами обработки, либо напрямую контроллируется специально обученным полковником - то это вполне нормально работает.

Вообще не очень понятно почему тема ушла в банкоматы, если это утилитарная вещь и ее реализовать можно многочисленными способами.

Причем эти два - это то что пришло в голову сразу. Существующие банкоматы, если я правильно понял ваши слова - вообще менять не надо, что бы они работали с mireapay. Сделать для них адаптер, который будет выполнять нужные команды - это вопрос 4-12 человеко-часов. Во всяком случае, если как вы говорите, ему надо сказать "да" или "нет".

Вы реально не понимаете? :-)
Есть "бизнес правило" - "со всех банкоматов для всех клиентов не выдавать налички на сумму более X миллиардов рублей за сутки" - даже если у клиентов (у каждого в отдельности) средства на контрактах/счетах есть... Именно это правило должно проверять до того как проверять есть у клиента средства или нет...
Все просто... :-)
Но без блокировок и транзакций (в которых проверяется данное условие при 1000 рпс по проверке одной суммы) есть идеи как это реализовать?

Делаете всем банкоматам, у которых есть лимит один кошелек. Делаете правило, что на баланс в этот кошелек нельзя переводить больше, чем Х рублей за период.
Количество рпс значения не имеет. Все операции можно проводить параллельно.

Вариант 2, делаете специальный ресурс "лимит", который банкоматы "покупают". В этом случае у всех банкоматов может быть свой кошелек.
Т.е. у вас будет контракт, состоящий из:
1. Перевод Х от клиента банкомату;
2. Банкомат покупает на Х лимитов с спец. кошелька;
3. Покупка у банкомата клиентом банкнот с серийниками, ну или если их нет - просто пишем, что "выдача наличных средств из банкомата YYY".
Т.к. каждый ресурс (а деньги на балансе - это ресурс) нужно в начале подготовить к списанию, то ваш лимит выглядит вообще просто - обычный ресурс, каждый день ставите лимит в Х миллиардов рублей по cron-правилу и все. Наступило 00:00 и не важно, сколько сейчас лимит - делаете его Х млрд рублей. И подключаете ваши банкоматы, хоть все сразу на покупку лимитов у кошелька. Количество рпс значения не имеет от слова полностью. Если решите домашнее задание, то поймете, что упретесь в сетевые адаптеры и IOPS. В этой статье не просто так в домашнем задании сказано про резервирование товаров. Это универсальный алгоритм. Так же как и протокол общения с ресурсными подсистемами, такими как баланс - он универсальный.


И если в первом случае сделать лимит очень сложно (на самом деле сложно, лично я браться не буду за такое), то в случае с покупкой банкоматом лимита с какого-то спец. кошелька - это вообще легко и просто. И даже если по каким-то причинам банкомат деньги не выдаст, то просто отменим контракт, потому что банкомат не подтвердил выдачу (у контракта есть возможность сделать так, что бы стороны подтвердили, что можно завершать, когда все готово к процессу завершения). Но у вас вроде как есть "установка" на да или нет, так что вам явно не подходит более безопасный вариант.

И еще, про этот лимит вы мне сейчас говорите.

UPD: на самом деле можно даже ресурс "лимит" не создавать. Просто на кошельке держать деньги, которые могут быть переданы только банкоматам и больше никому. Система это прямо сейчас умеет. В этом случае даже усложнять ничего не придется. Оно просто будет работать.

UPD2: Для сервиса Баланс будет лучше, если лимит будет не устанавливаться в Х каждый день, а будут создаваться балансы заранее, в которых будет прописано, что АктивноС и АктивноДо - это с начала дня и до начала следующего дня. С точки зрения архитектуры сервиса Баланс, в т.ч. на данный момент это будет более правильным решением. Огромный +, что записи можно создавать заранее и не беспокоится, что что-то пройдет не так, а если и пойдет - сразу звать тех поддержку.

Java — великолепный инструмент для прототипирования и отладки алгоритмов, решений, но итоговый продукт все равно должен быть воплощён в железе и максимально эффективно его утилизировать. Не нужно считать эти слова пустыми, автор вкладывает в них смысл — не надо транжирить ресурсы впустую.

Не я один значит думал о таком, что вместо докупки железа можно просто ресурсоемкие и нагруженые задачи выкинуть в нативные подпрограммы. Однако насчет хорошего инструмента для отладки я бы поспорил, переписывание с джавы потребует серьезной переделки и отладки заного. Джава это не питон, в котором модули типа thread asyncio, практически соответствуют реализациям тредов и корутин в С и С++ и довольно легко на них перекладываются. Так что как раз питон отлично подходит для отладки и прототипирования если цель в дальнейшем перенос на нативный код, а джава нет.

Бизнес логика не зависит от языка реализации. Вы не можете сделать сложение двух чисел разными способами, отличающимися от языка к языку.

Вот если мы будем говорить про криптографию, векторные операции - тогда да. Джава не подходит, потому что не умеет, но обычные if-else программы работают одинаково везде. Ветвление не удастся сделать как-то иначе, чем это позволяет оборудование.

Но, если мы говорим про общий случай, когда речь идет о произвольной программе из всего множества возможных, тогда да, я с вами согласен, но речь шла не про общий случай в статье =)

С и С++ не подходят для прикладных приложений.
Я бы вообще уже постарался бы выводить их из использования, потому что они устарели по всем показателям.

Главная проблема С и С++ в том, что нужно быть мега-крутым, что бы что-то дельное писать, но что бы стать мега-крутым, надо кучу программ написать.
И когда ты приложение напишешь - тебе никто не сможет сказать, что все работает правильно.

Но в целом с видосом согласен =) Поэтому и писал на Java изначально.
Только нужно учитывать, что сервис проектировался таким образом, что у него есть ядро, которое можно написать один раз и больше не трогать - потому что не нужно.

Большая часть микросервисов такой фокус не провернет. Постоянно что-то менять надо. И менять много!

С и С++ не подходят для прикладных приложений.

А что подходит? Просто пытаюсь представить на чем еще писать гуеваое приложение с библиотеками или игровой движок. Кросплатформенный разумеется.

Есть и другие ЯП, компилируемые в исполняемые файлы. Некоторые даже используют тот же тулчейн, что и gcc.

Докину на подумать. Это же микросервис. Значит его могут погасить в любой момент. Попробуйте проверить что алгоритм корректно отрабатывает если его прервать в любом месте, например сразу после вычитки сообщений :)

Это как раз предполагается. Вариант, что штекер вытащили и все рухнуло. Даже в этом случае все должно восстанавливаться.

Если это какой-то междусобойчик для просветленных, то зачем он в паблике на хабре. Если нет, то непонятно как минимум ничего. Почему отказ от транзакций? Какая государственная система? Причем здесь Эльбрус? Чем автора не устроила производительность jvm, какой версии и с чем он сравнивал?

Слово "транзакция" пришло в программирование из финансовой сферы 70 лет назад, поэтому утверждение о том, что финансовые операции теперь будут проводится без транзакций (и блокировок им сопутствующих) лишь наводит на мысли о многочисленной службе поддержки, вручную исправляющей поток ошибок целостности.

Речь идет о транзакции, которая запускается при работе с БД с целью выполнения запросов в рамках одного окна. Если происходит ошибка или иная проблема - все изменения откатываются.

Именно эти транзакции и не требуются для работы с финансовыми данными.

Именно эти транзакции требуются для работы с финансовыми данными

Именно они и не нужны для проведения платежей. Вы видимо ни эту статью не читали, ни предыдущие. И в код не заглядывали, хотя ссылки есть.
Не вижу смысла с вами спорить, потому что вы ожидаете определенный ход вещей, а все иное для вас по определению ошибка.

Это вопрос не технологии, а предметной области. Для гарантированного перевода денег со счёта на счёт используется транзакция. Вы можете называть подобную операцию как угодно, не пользоваться готовыми средствами СУБД или монитора транзакций, а реализовать свой "аналоговнет" механизм атомарности, но суть от этого не меняется.

Вот именно в предметной области вы и не разбираетесь, потому что не понимаете азов информатики. Изучите для началу теорию, потом возвращайтесь.

Sign up to leave a comment.

Articles