Wydajna architektura do przetwarzania adresów w USA
Istniejący system klienta do parsowania adresów z Address Information System (AIS) i Topologically Integrated Geographic Encoding and Referencing (TIGER) został zbudowany w oparciu o MS SQL Server i SSIS. Wykorzystywał połączenie procedur składowanych, bibliotek C# z wyrażeniami regularnymi oraz funkcji do parsowania, weryfikacji i oczyszczania danych.
Choć system działał, nie radził sobie z dużym ruchem i dużymi zbiorami danych. Nasz zespół wdrożył zoptymalizowaną architekturę systemu Black stork, przenosząc funkcje do rozwiązania opartego na Redis, optymalizując algorytmy, wdrażając buforowanie oraz mechanizmy deduplikacji. Dzięki tym usprawnieniom szybkość przetwarzania wzrosła o 50%, a obciążenie ruchem zostało zminimalizowane.
Kluczowe wyzwania w projekcie
Niska wydajność
System zaczynał zwalniać podczas przetwarzania ponad miliona rekordów. MS SQL Server i SSIS nie były w stanie skalować się do takiego wolumenu, a złożoność procedur składowanych dodatkowo pogarszała sytuację. Opóźnienia były nieakceptowalne dla klienta, który potrzebował szybkiego przetwarzania na potrzeby operacji biznesowych. Aby rozwiązać problem, musieliśmy całkowicie przeprojektować architekturę.
Trudne zarządzanie
Kontrolowanie przepływu danych w starym systemie było kolejnym poważnym wyzwaniem. Przetwarzanie żądań i odpowiedź systemu trwały długo, a opóźnienia były nieregularne. Nie można było przewidzieć, kiedy dane faktycznie zostaną dostarczone. Brakowało nam również narzędzi pozwalających podejmować działania naprawcze w przypadku opóźnień.
Aktualizacje
Jednym z głównych wymagań klienta było otrzymywanie świeżych danych co miesiąc. Około 80–90% nowych danych okazywało się duplikatami rekordów już zapisanych w systemie. Wielokrotne ładowanie tych samych danych powodowałoby zbędne opóźnienia i zajmowało przestrzeń dyskową. Naszym celem było wdrożenie rozwiązania rozróżniającego nowe i istniejące rekordy oraz dopuszczającego do przetwarzania wyłącznie świeże dane.
Nieprawidłowe dane wejściowe
Rygorystyczne algorytmy dopasowywania nie uwzględniały drobnych różnic, przez co nie odnajdywano wielu prawidłowych adresów. Jeśli na przykład w nazwie ulicy lub miasta występowała pomyłka w jednej literze, system zwracał wynik negatywny. Skoncentrowaliśmy się więc na ulepszeniu algorytmów, aby zwracały prawidłowe rezultaty również przy niewielkich błędach w danych wejściowych.
Różne formaty
Adresy w Portoryko mają nieco inną strukturę niż standardowe adresy w kontynentalnej części Stanów Zjednoczonych. System traktował wszystkie adresy jednakowo, co w przypadku adresów portorykańskich prowadziło do błędnej interpretacji i niedopasowania danych. Powodowało to dużą liczbę błędów. Aby rozwiązać problem, musieliśmy zaprojektować osobny algorytm uwzględniający różnice regionalne.
Ograniczenia technologiczne
Połączenie MS SQL Server, SSIS i niestandardowych procedur składowanych nie zostało zaprojektowane z myślą o szybkim wzroście wolumenu danych. Wraz z rozwojem system stawał się coraz trudniejszy w zarządzaniu i utrzymaniu. Było jasne, że używane technologie osiągnęły swoje granice i potrzebne jest bardziej elastyczne, skalowalne rozwiązanie odpowiadające zmieniającym się potrzebom klienta.
Etapy wdrożenia zoptymalizowanego systemu przetwarzania adresów
Przeprowadziliśmy szczegółową analizę wydajności za pomocą JetBrains DotTrace. Pozwoliło nam to zmierzyć szybkość każdej funkcji i wskazać elementy spowalniające system. Skupiliśmy się przede wszystkim na zapytaniach MSSQL i algorytmach parsowania adresów, które odpowiadały za największe wąskie gardła.
Aby zwiększyć wydajność, przenieśliśmy dane z MSSQL, gdzie początkowo były przechowywane w formacie JSON, do Redis. Zapewniło to szybsze operacje odczytu i zapisu oraz lepszą obsługę dużych zbiorów danych. Rozdzieliliśmy też dane między wiele instancji Redis, co usprawniło parsowanie i geokodowanie adresów. Rozproszona architektura pozwoliła systemowi przetwarzać dane znacznie szybciej.
Wdrożyliśmy wstępnie skompilowane zapytania MSSQL bezpośrednio współpracujące z Redis, co przyspieszyło przepływ danych między algorytmami parsowania a bazą. Programiści NannosTech opracowali sześć algorytmów, w tym jeden przeznaczony specjalnie dla Portoryko. Dzięki nim system odnajduje właściwy adres nawet przy drobnych błędach wejściowych. Podzieliliśmy również rekordy ZIP+4 na dwie części: pierwsza służy do początkowego parsowania, a druga do zbudowania pełnego wyniku adresowego.
Aby ograniczyć zbędne operacje, wprowadziliśmy wewnętrzny system cache. Umożliwiło to przechowywanie ostatnio przetworzonych rekordów i szybki dostęp do nich. Dzięki temu system działał szybciej, zwłaszcza podczas przetwarzania wsadowego, w którym często pojawiały się podobne dane. Do skalowania i deduplikacji użyliśmy Hadoop. Apache Solr służył do indeksowania, poprawiając wyszukiwanie i pobieranie danych w całym systemie.
Przez cały projekt regularnie testowaliśmy system za pomocą JetBrains DotTrace, aby upewnić się, że każdy komponent działa z optymalną wydajnością. Na podstawie wyników dostrajaliśmy algorytmy i mechanizmy cache, dzięki czemu końcowe rozwiązanie spełniło wyznaczone cele dotyczące szybkości, skalowalności i wydajności.
Technologie wykorzystane w projekcie
REDIS
MS SQL
C#
Hadoop
Apache Solr
JetBrains DotTrace
Rezultaty: większa szybkość i skalowalność
Stworzyliśmy wysoce uporządkowany i skalowalny katalog adresów na podstawie danych z AIS i TIGER. Nowy system umożliwia klientowi automatyczne uzupełnianie niekompletnych adresów o brakujące elementy (miasto, kod pocztowy lub stan) oraz zapewnia solidny mechanizm walidacji, który gwarantuje poprawność wszystkich elementów adresu.
- 2x szybsze przetwarzanie danych
- 40% mniej ruchu związanego z przetwarzaniem dzięki uporządkowanym katalogom
- Stabilny i łatwo skalowalny system obsługujący ponad 1 milion rekordów
- Zoptymalizowane przetwarzanie wsadowe z wykorzystaniem buforowania
- Deduplikacja danych umożliwiająca szybsze i bardziej efektywne wykorzystanie zasobów podczas ładowania nowych danych
- Nowe algorytmy wykrywania adresów nawet wtedy, gdy zawierają błędy