Exactly-once სემანტიკა
რა არის exactly once სინამდვილეში
„exactly-once“ ხშირად ესმის ორი განსხვავებული რამ:- ადგილზე მიტანა: შეტყობინება მომხმარებელს ზუსტად ერთხელ გადაეცემა.
- დამუშავება: საბოლოო გვერდითი ეფექტი (ჩაწერა DD- ში, ბალანსის შეცვლა, სხვა მოვლენის ემისია) მოხდება ზუსტად ერთხელ, თუნდაც უფრო მეტი მიწოდება ან მცდელობა.
განაწილებულ სისტემებში უფრო საიმედოა საუბარი დამუშავების სემანტიკაზე. ადგილზე მიტანა ზუსტად ერთხელ რთულია (დუბლიკატები და გამეორებები გარდაუვალია), მაგრამ შეიძლება დარწმუნდეს, რომ საბოლოო მდგომარეობა ერთადერთი დამუშავების ტოლფასია.
როდესაც EOS საჭიროა და როდის არა
საჭიროა EOS, თუ:- ფულადი გარიგებები და ნაშთები: ორმაგი ჩამოწერა დაუშვებელია.
- ლიცენზიების/კვოტების აღრიცხვა, ბილინგის მრიცხველები.
- შეუქცევადი გარე გამოწვევები (მაგალითად, გასაღების ერთჯერადი გააქტიურება).
- ეფექტები არის გადაქცეული ან კომპენსირებული (საგები, ზარები).
- ნებადართულია დროებითი დუბლიკატები ფანჯრებში/ლოგოებში.
- უფრო იაფია idempotent sink- ის მიწოდება, ვიდრე გარიგებების გადატანა მთელი ტრაქტის საშუალებით.
მოდელი: end to-end vs. hop-by-hop
Hop-by-hop EOS: თითოეული განყოფილება (წყარო - პროცესორი - მიმღები) უზრუნველყოფს, რომ იგი გამოიყენებს თავის მოქმედებას ზუსტად ერთხელ.
End-to-end EOS: მთელი ჯაჭვი უზრუნველყოფს, რომ „ფაქტიდან“ „გვერდითი ეფექტის“ შედეგიდან შედეგი ექვივალენტურია ერთი დამუშავებისთვის.
პრაქტიკაში, end-to-end მიიღწევა გარიგების ან/და idempotent- ის კომბინაციით თითოეულ ჰოპში.
ძირითადი სამშენებლო ბლოკები
1. იდემპოტენტური ოპერაციები
ოპერაციის გასაღები იგივე მოთხოვნის გამეორება იგივე შედეგს იძლევა.
Ключи: `idempotency_key`/`event_id`/`operation_id`.
განხორციელება: „ნახული“ ოპერაციების ცხრილი TTL- ით - შეყვანის ლოგოს გადაკეთება.
2. გარიგებები „მე ვკითხულობ და ვწერ“ (read-process-write)
მუშაობის ერთ ბირთვულ ერთეულში აღირიცხება გვერდითი ეფექტი და კითხვის პროგრესი (ოფსეტური/პოზიცია). ეს აღმოფხვრის „მოჩვენებებს“, როდესაც ნაბიჯებს შორის დაცემისას.
3. ვერსია/SEQUENCE
დანაყოფისთვის ინახება ვერსია/მრიცხველი; ცვლილებები გამოიყენება მხოლოდ იმ შემთხვევაში, თუ „გაფართოებული _ ვერსია“ ემთხვევა. იგივე მოვლენის გამეორება არ ზრდის ეფექტის ვერსიას ერთხელ.
4. დედუპლიკაცია
ინდექსი '(consumer _ id, event _ id)' ან ბუნებრივი 'ბიზნეს _ id "ოპერაციების მიხედვით.
განხორციელების ნიმუშები
1) გარიგების ლოგი + გარიგების სინკი ოფსეტური დაფიქსირებით
იდეალურია ნაკადის დამუშავებისთვის.
ჩვენ ვკითხულობთ ლოგოსგან (მხოლოდ დადასტურებული ჩანაწერები).
ჩვენ ვასრულებთ დამუშავებას.
- ა) ჩაწერეთ ეფექტი sink (BD/ცხრილში),
- ბ) ჩაწერეთ „წაიკითხეთ ოფსეტი N“ (იმავე მონაცემთა ბაზაში).
- კომუნა. ჭიდაობის დროს, ან ყველაფერი ხდება (და ოფსეტი გადაადგილდება), ან არაფერი.
თვისებები: განმეორებითი შესრულება არ ზიანს აყენებს; „ზუსტად ერთხელ“ ეფექტზე, თუნდაც მესიჯი ორჯერ წაიკითხოს.
2) Outbox + idempotent Consumer
გარიგების სერვისების მწარმოებლებისთვის.
ერთ DD გარიგებაში: ჩვენ ვცვლით დომენის ჩანაწერს და ვწერთ მოვლენას გარედან.
რეპლიკატორი აწვდის მოვლენას იმავე 'ღონისძიების _ id' საბურავზე.
Consumers იყენებენ მოვლენებს idempotent ('event _ id').
თვისებები: პროდიუსერი უზრუნველყოფს, რომ ფაქტი არ დაიკარგება; კონსუტერები უზრუნველყოფენ ზუსტად ერთ ეფექტს.
3) EOS Kafka/Flink მსგავსი სისტემებში (კონცეფციურად)
Idempotent- ის პროდიუსერი: ის იცავს დუბლებს გაგზავნის დროს.
პროდიუსერის გარიგებები: ტოპიკის ჩანაწერების ჯგუფი + კონსიუმერის ცვლა ხდება ატომურად; მკითხველები იყენებენ იზოლაციას 'read _ committed'.
დამუშავების მხარე ინახავს სახელმწიფოს (სახელმწიფო მაღაზიას) და აკავშირებს მას გარიგებასთან ერთად.
თვისებები: ნაკერების/ჩაძირვის ხელახალი გაშვება არ იწვევს ორმაგ ეფექტს; დუბლიკატები „არ ჩანს“ downstream.
4) Idempotent „sinks“ (sinks) upsert/merge მეშვეობით
Sink იღებს 'operation _ id '/' event _ id' და ასრულებს 'UPSERT... WHERE NOT EXISTS`.
გვერდითი ეფექტი (მაგალითად, დარიცხვა) ხორციელდება ატომურად, შემოწმებით „უკვე არ გამოიყენებოდა“.
თვისებები: EOS იაფი მეთოდი საცავთან საზღვარზე, განაწილებული გარიგების გარეშე.
განხორციელების ძირითადი დეტალები
ოპერაციის იდენტიფიკატორები
გამეორებისთვის უნდა იყოს დეტერმინირებული (ნუ გამოიმუშავებთ ახალ UUID- ს ჭიდაობის დროს).
გქონდეთ სტაბილური ხილვადობის არეალი (კონსიუმერზე/ერთეულზე/სისტემაზე).
დედაპლაციის ცხრილი
Колонки: `consumer_id`, `operation_id`, `applied_at`, `ttl_expires_at`.
ინდექსები '(consumer _ id, ოპერაცია _ id)'.
TTL არის გამეორების მაქსიმალური ფანჯარა (ლოგოს გადაკეთება + პოტენციური შეფერხებები).
ოპტიმისტური კონკურენცია
შეინახეთ დანაყოფის ვერსია write მოდელში.
ღონისძიების/ბრძანებების გამოყენებისას გამოიყენეთ 'WHERE ვერსია =: გაფართოებული "; დუბლიკატი არ გაზრდის ვერსიას.
შეკვეთა/შეკვეთა
EOS არ არის ტოლი „ზუსტად იგივე წესრიგით“. უზრუნველყეთ თანმიმდევრულობა წვეულების გასაღების საშუალებით (განყოფილების ყველა მოვლენა - ერთი წვეულება) ან/და შედარება „sequence“.
Idempotent გარე ზარები
არასასურველი მეთოდებისთვის (მაგალითად, HTTP ვებჰუკი მესამე მხარის სერვისში) დაამატეთ 'Idempotency-Key "და მოითხოვეთ, რომ პარტნიორმა მხარი დაუჭიროს მას.
ხშირი ხაფანგები
EOS მხოლოდ ერთ ადგილზეა: თუ sink imempotent- ია, მაგრამ მეორეხარისხოვან მოვლენებს იდემპოტენტობის გარეშე გამოსცემთ, მიიღებთ „ზუსტად ბევრჯერ“ downstream- ს.
ორი კომიტა: ჯერ BD- ში, შემდეგ ოფსეტური კომუნიკაცია ბროკერში - მათ შორის ვარდნა ქმნის ეფექტების დუბლიკატებს.
ნედლეული CDC გარედან: BD სქემის ცვლილება არღვევს მომხმარებელთა imempotence.
არასტაბილური გასაღებები: 'operation _ id' დამოკიდებულია დროზე/რანდომზე და იცვლება ჭიდაობის დროს.
ღირებულება და კომპრომისი
ლატენტობა: გარიგებები/იზოლირებული კითხვები, ზრდა p95/p99.
საცავის ზეგანაკვეთური: ბაბუის ცხრილები, სახელმწიფო ფერდობები, გარიგების ლოგოები.
ოპერაციის სირთულე: გარიგების დრო, ნაკადის განმეორება, „ჩაძირული“ სესიები.
დიაგნოზი: მეტი სახელმწიფო („კაიტაში“, „თქვენ ხედავთ, როგორც read _ committed“, „გამოტოვებულია“).
შეარჩიეთ EOS წერტილოვანი: კრიტიკული აგრეგატებისთვის და ეფექტებისთვის; დანარჩენი დაფარეთ იდემპოტენტურობით და კომპენსაციით.
Exactly once ტესტირება
1. Fault-injection: პროცესის ვარდნა ნაბიჯებს შორის „დაწერა ეფექტი“ და „დაფიქსირდა ოფსეტური“.
2. დუბლიკატები: იგივე შეტყობინება 2-5 ჯერ გადაიტანეთ, დარწმუნდით ერთ ეფექტში.
3. Restarts და rebalance: workers- ის გაჩერება/გადატვირთვა, ორმაგი დამუშავების არარსებობის შემოწმება.
4. ქსელის ფლოპი: ტაიმაუტები გარიგების შუაში, კომუნის განმეორება.
5. დატვირთული ტესტები: რიგების ზრდა, არის თუ არა დეგრადაცია „სამუდამოდ გარიგებებში“.
მინი შაბლონები (ფსევდო)
Idempotent sink, რომელიც ფიქსირდება ოფსეტური
pseudo begin tx if not exists(select 1 from dedup where consumer_id=:c and op_id=:id)
then apply_effect(...) -- upsert / merge / add_one_time_action insert into dedup(c, id, applied_at) values(:c,:id, now)
end if update offsets set pos=:pos where consumer_id=:c commit
გუნდი დანაყოფის ვერსიით
pseudo begin tx update account set balance = balance +:delta,
version = version + 1 where id=:account_id and version=:expected_version;
if row_count=0 then error CONCURRENT_MODIFICATION commit
უსაფრთხოება და შესაბამისობა
PII/PCI დედაპლატის ცხრილებში: შეინახეთ მინიმუმი, გამოიყენეთ ნიშნები „ნედლეული“ მონაცემების ნაცვლად.
აუდიტი: operation _ id ',' trace _ id ", შედეგი (APLIED/ALREADY _ APLIED).
შენახვის პოლიტიკა: TTL დღის ცხრილებზე, ოფსეტური/ლოგოების არქივირება.
ანტი შაბლონები
„ნამდვილი exactly-once მიწოდება“: სატრანსპორტო პროტოკოლის დონეზე დუბლების აღმოფხვრის მცდელობა ეფექტის imppotence გარეშე.
გლობალური განაწილებული გარიგებები ყველაფრისთვის: XA/2PC ყველა სერვისის საშუალებით - მყიფე და ნელა.
Indempotent- ის კასრების შერევა (მაგალითად, ელექტრონული ფოსტის გაგზავნა ოფსეტში).
ოპერაციის გასაღებების არარსებობა: დატვირთვის „უნიკალურობაზე“ დაყრდნობით.
წარმოების ჩეკის სია
თითოეულ კრიტიკულ ეფექტს აქვს იდემპოტენტური გასაღები.
- offset/კითხვის პოზიცია აღირიცხება ერთ გარიგებაში ეფექტით.
- ბაბუის ცხრილები ინდექსირებულია; TTL - ლოგოს რეტენციები.
- დანაყოფებისთვის, ოპტიმისტური კონკურენცია (ვერსია/სექცია) შედის.
- ნაკადები/ტოპები იკითხება „მხოლოდ დამამშვიდებელი“ რეჟიმში (თუ შესაძლებელია).
- დუბლიკატებისა და ვარდნის ტესტები წარმოდგენილია CI/CD- ში.
- დაშბორდი: გამეორებების წილი, წარუმატებელი გარიგებები, დაბლოკვის დრო, ლაგები.
- დოკუმენტაცია Idempotency-Keu ინტეგრატორებისთვის/გამეორებები/ტაიმაუტები.
FAQ
შესაძლებელია EOS- ის უზრუნველყოფა გარიგების გარეშე?
ხშირად დიახ - sink's (upsert/merge) და აგრეგატების ვერსიის საშუალებით. გარიგებები ამარტივებს გარანტიებს, მაგრამ ზრდის ღირებულებას.
ყველას სჭირდება „exactly-once“?
არა. ის ძვირფასია. გამოიყენეთ წერტილოვანი, სადაც კომპენსაცია შეუძლებელია/გზაზე.
როგორ დააკავშიროთ წერილები/ვებჰუკები EOS- სთან?
ბუფერული შეტყობინება კომიტამდე, გაგზავნეთ ეფექტის დაფიქსირების შემდეგ; შეინახეთ 'notification _ id' და გაგზავნეთ idempotent.
რა არის უფრო მნიშვნელოვანი - მიწოდება ან დამუშავება?
დამუშავება. მიწოდებები შეიძლება განმეორდეს; საბოლოო მდგომარეობა უნდა იყოს სწორი და ერთადერთი.
შედეგი
Exactly-once არის ეფექტის სისწორეზე და არა გაყვანილობის დროს დუბლების არარსებობაზე. იგი მიიღწევა idempotent- ის ერთობლიობით, კითხვის ეფექტისა და პროგრესის ატომური ფიქსაციით, გონივრული განაწილებით და ვერსიის დისციპლინით. გამოიყენეთ EOS, სადაც შეცდომის ღირებულება მიუღებელია და შეამოწმეთ მისი რეალობა დაცემისა და დუბლების ტესტებით - არა ტრანსპორტის რწმენით.