Architekt systemówArchitekt systemów

Jak zaprojektowałbyś globalnie rozproszony, wrażliwy na opóźnienia magazyn cech, który dostarcza wstępnie obliczone cechy ML do punktów infencji w czasie rzeczywistym w różnych regionach chmurowych, zapewniając opóźnienie odczytu na poziomie mikrosekund dla gorących cech poprzez wielopoziomowe buforowanie, utrzymując silną spójność między wartościami cech online i offline podczas operacji wypełniania danych, oraz implementując automatyczne wykrywanie dryfu cech z wyzwalaczami ponownego trenowania modeli międzyregionowych?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź na pytanie

Architektura wykorzystuje wzór dual-store, który ściśle oddziela online'owe serwowanie od offline'owych zagadnień związanych z treningiem. Warstwa online korzysta z Redis Cluster wdrożonego na instancjach z pamięcią masową NVMe w każdym regionie, z Envoy Proxy jako lokalnym rozkładaczem obciążenia i terminatorem TLS. Aktualizacje cech przechodzą przez Apache Kafka działający jako niezmienny dziennik zmian, z Debezium jako łącznikami CDC, które rejestrują mutacje z baz danych operacyjnych i przesyłają je do regionalnych konsumentów Redis.

Dla przechowywania offline, historyczne cechy są kompresowane do tabel Apache Iceberg na S3, co umożliwia zapytania z podróżą w czasie oraz wydajne przetwarzanie wsadowe za pomocą Apache Spark. Spójność podczas wypełniania danych osiąga się dzięki wersjonowaniu zegarów wektorowych: każda wartość cechy ma logiczny znacznik czasu, a skrypty Lua w Redis wykonują atomowe operacje porównania i zamiany, aby odrzucać zapisy porządkowe, co zapewnia, że ścieżka służąca nigdy nie obserwuje częściowych stanów wypełniania.

Wykrywanie dryfu wykorzystuje histogramy Prometheus zbierane przez zadanie Apache Flink wykonujące analizy statystyczne w czasie rzeczywistym na rozkładach cech. Gdy KL-walizacja lub wskaźnik stabilności populacji przekracza progi, Flink wyzwala Argo Workflows w celu zorganizowania ponownego trenowania modeli międzyregionowych oraz wdrożeń kanaryjnych.

Sytuacja z życia

Międzynarodowa firma fintechowa wymagała możliwości wykrywania oszustw w czasie rzeczywistym w różnych regionach AWS, Azure i w lokalnych centrum danych. Krytycznym wyzwaniem było dostarczanie cech agregacji ruchomej - takich jak prędkość transakcji użytkownika w ciągu ostatniej godziny - do punktów infencji z opóźnieniem poniżej 5 ms. Ich istniejące repliki odczytu PostgreSQL cierpiały na opóźnienia replikacji przekraczające 200 ms podczas szczytowych obciążeń, co powodowało, że modele oceny oszustw działały na przestarzałych danych i przegapiały skoordynowane ataki.

Rozwiązanie 1: Globalna baza danych aktywna-aktywna Wdrożenie CockroachDB lub Google Spanner obiecywało izolację seryjną i automatyczną globalną replikację. To podejście wyeliminowało problemy ze spójnością, ale wprowadziło opóźnienia zapisu międzyregionowego przekraczające 100 ms z powodu narzutu konsensusu Paxos. Dla cech o wysokiej szybkości wymagających natychmiastowej widoczności nowych transakcji to opóźnienie okazało się nie do zaakceptowania. Ponadto koszty operacyjne rosły kwadratowo w związku z przepustowością odczytu, co czyniło to nieekonomicznym rozwiązaniem dla wymagań dotyczących serwowania na poziomie milisekund.

Rozwiązanie 2: Spójność lokalna z regionalnymi buforami Implementacja niezależnych klastrów Redis w każdym regionie z asynchroniczną replikacją za pomocą Kafka MirrorMaker zapewniła doskonałą wydajność odczytu i liniową skalowalność. Jednak stwarzało to krytyczne luki w spójności podczas operacji wypełniania, gdy naukowcy danych ponownie obliczali historyczne cechy, aby skorygować problemy z jakością danych. Bez ścisłych gwarancji wersjonowania system serwował przestarzałe agregaty obok świeżych, prowadząc do zniekształceń oceny modelu i błędnych ocen ryzyka, które fałszywie oznaczały legalne transakcje.

Rozwiązanie 3: Wielopoziomowe buforowanie z zegarami wektorowymi (Wybrane) Zaprojektowaliśmy system wielopoziomowy wykorzystujący Redis jako gorącą warstwę i Kafka jako niezmienny źródło prawdy. Każda wartość cechy miała znacznik czasu zegara wektorowego pochodzący z rurociągu przetwarzania. Podczas wypełniania, zadania Spark zapisywały na S3, emitując jednocześnie wersjonowane zdarzenia do Kafka. Regionalni konsumenci stosowali aktualizacje za pomocą skryptów Lua w Redis, które wykonywały porównanie zegara wektorowego po stronie serwera, atomowo odrzucając zapisy porządkowe i akceptując nowsze wersje. Dla wykrywania dryfu, zainstrumentowaliśmy rozkłady cech za pomocą histogramów Prometheus, przekazując je do Flink w celu przeprowadzenia rzeczywistej analizy statystycznej w porównaniu z bazowymi danymi treningowymi.

Wynik zredukował opóźnienie P99 do 1,2 ms na całym świecie, wyeliminował naruszenia spójności podczas wypełnień i zmniejszył incydenty degradacji modelu o 94% dzięki automatycznym potokom ponownego trenowania wyzwalanym przez dryf.

Co często umykają kandydatom

Jak zapobiegać zakażeniu pamięci podręcznej podczas masowych wypełnień historycznych cech, gdy warstwa serwująca online musi pozostać dostępna?

Wielu kandydatów sugeruje po prostu wstrzymanie serwowania podczas wypełnienia lub użycie rozproszonych transakcji obejmujących pamięć podręczną i bazę danych. Właściwe podejście wdraża logiczne znaczniki czasu i przestrzenie kluczy w trybie cienia. Strumienie danych wypełniających przepływają przez oddzielny temat Kafka z monotonnie rosnącymi identyfikatorami wersji. Klastry serwujące online utrzymują dwa przestrzenie kluczy Redis: „aktualne” i „przygotowawcze”. Wypełnienie zasila przestrzeń przygotowawczą, podczas gdy serwuje odczyty z aktualnej. Po zakończeniu atomowa operacja RENAME w Redis zamienia przestrzenie kluczy w mikrosekundach, lub alternatywnie, warstwa aplikacji pyta o obie przestrzenie kluczy i wybiera wartość o wyższej wersji. To zapewnia zerowy czas przestoju i zapobiega serwowaniu częściowych stanów wypełnienia bez skomplikowanych protokołów koordynacyjnych.

Jaki model spójności powinien regulować związek między magazynami cech online i offline, i dlaczego silna spójność nie sprawdza się w skali?

Kandydaci często błędnie opowiadają się za transakcjami ACID obejmującymi zarówno Redis, jak i S3 za pomocą protokołów dwóch etapów. Magazyn offline optymalizuje pod kątem przepustowości i niezmienności wsadowej, podczas gdy magazyn online optymalizuje pod kątem niskiej latencji punktowych odczytów. Silna spójność wymaga narzutu konsensusu, który wprowadza nieakceptowalne opóźnienia w ścieżce serwisowej. Zamiast tego adoptuj spójność eventualną z gwarancjami ograniczonego opóźnienia. Wykorzystaj kompaktowanie dzienników Kafka z oknem pojednania opartym na retencji, aby zapewnić, że magazyn online zbiega się ze stanem magazynu offline w określonym czasie. Dla cech wymagających surowszych gwarancji implementuj buforowanie poprzez zapis, gdzie potwierdzenie zapisu online czeka na potwierdzenie złożenia Kafka, akceptując nieco wyższą latencję dla krytycznych cech przy jednoczesnym zachowaniu dużej przepustowości dla innych poprzez asynchroniczną replikację.

Jak radzisz sobie z wersjonowaniem cech podczas testów A/B modeli wymagających niekompatybilnych transformacji tych samych danych surowych?

Typowym błędem jest wersjonowanie tylko artefaktu modelu, ignorując ewolucję schematu cech, co prowadzi do zniekształcenia między treningiem a serwowaniem. Rozwiązanie wdraża przestrzenie nazw cech i śledzenie pokrewieństwa za pomocą DataHub lub Apache Atlas. Każda transformacja cechy uzyskuje wersję semantyczną. Magazyn cech utrzymuje wiele wersji jednocześnie w Redis, używając prefiksowanych kluczy. Konfiguracje serwowania modeli określają wymagane wersje cech za pomocą Consul lub etcd. Podczas promowania modelu z trybu cienia do produkcji, warstwa orkiestracyjna wstępnie podgrzewa pamięci podręczne dla nowej wersji cechy za pomocą odtworzenia historycznego z Kafka, zanim ruch przełączony. To pozwala na równoczesne testy A/B przy użyciu niekompatybilnych obliczeń cech bez wycieku danych między kohortami eksperymentów lub skoków latencji zimnego startu.