Data Import Handler – sharding

Nasza czytelniczka (pozdrawiamy!) zgłosiła się do nas z problemem dotyczącym współpracy DIH z shardingiem. Wiki projektu SOLR pokazuje moim zdaniem rozwiązanie tej kwestii, ale czyni to trochę na około i przy okazji.

Co to jest sharding?

Sharding oznacza podział danych na kilka części oraz przechowywanie i obróbkę tych danych niezależnie. Dodatkowa logika w ramach aplikacji pozwala na wybranie odpowiedniej części zbioru danych i/lub łączenie wyników z poszczególnych źródeł. W przypadku DIH i shardingu możemy mieć do czynienia z następującym przypadkiem:

  • sharding po stronie źródło danych – czyli wiele lokalizacji / tabel zawierających poszczególne części zbioru danych
  • sharding po stronie SOLR – czyli podzielenie danych ze źródła na wiele niezależnych instancji SOLR
  • oba powyższe jednocześnie

W opisywanym przypadku mamy jeden zbiór danych i chcemy stworzyć wiele zbiorów (tzw. shardów) po stronie SOLR.

Kiedy stosować sharding?

Bardzo ważna kwestia: po co? W moim mniemaniu sharding bywa zbyt często nadużywany generując mnóstwo dodatkowych komplikacji i ograniczeń. Główny powód to duży wolumen danych, które powodują, że indeks SOLR nie mieści się w obrębie jednej maszyny. Jeśli tak nie jest – często oznacza to, że sharding jest zbędny. Kolejny powód to wydajność. Jednak sharding może tutaj pomóc tylko wtedy, gdy inne optymalizacje zawiodą a zapytania są na tyle skomplikowane, że sam narzut shardingu (przekazania zapytania do poszczególnych shardów i łączenie ich odpowiedzi) jest mniejszy niż zysk możliwy do uzyskania.

Dane testowe

Zakładamy jednak, że sharding jest nam potrzebny. W przykładzie poniżej użyłem danych z musicbrainz tworząc prostą tabelę postgresową:

Table "public.albums"
 Column |  Type   |                      Modifiers
--------+---------+-----------------------------------------------------
 id     | integer | not null default nextval('albums_id_seq'::regclass)
 name   | text    | not null
 author | text    | not null
Indexes:
"albums_pk" PRIMARY KEY, btree (id)

W tabeli znajduje się 825661 rekordów. Podkreślam tutaj, że zarówno struktura jak i ilość danych jest na tyle małe, że praktyczna przydatność shardingu jest tu pomijalna.

Instalacja testowa

Do testów użyjemy trzech instancji SOLR. Wszystkie instancje są identyczne, różnica jest związana tylko z numerem portów (8983, 7872, 6761) – testy będą wykonywane na jednej fizycznej maszynie.

Definicja w schema.xml:

<fields>
 <field name="id" type="string" indexed="true" stored="true" required="true" />
 <field name="album" type="text" indexed="true" stored="true" multiValued="true"/>
 <field name="author" type="text" indexed="true" stored="true" multiValued="true"/>
</fields>
<uniqueKey>id</uniqueKey>
<defaultSearchField>album</defaultSearchField>

Definicja DIH w solrconfig.xml:

<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
 <lst name="defaults">
  <str name="config">db-data-config.xml</str>
 </lst>
</requestHandler>

I plik DIH db-data-config.xml:

<dataConfig>
 <dataSource driver="org.postgresql.Driver" url="jdbc:postgresql://localhost:5432/shardtest" user="solr" password="secret" />
 <document>
  <entity name="album" query="SELECT * from albums">
   <field column="id" name="id" />
   <field column="name" name="album" />
   <field column="author" name="author" />
  </entity>
 </document>
</dataConfig>

W tym momencie każda instancja jest w stanie dokonać pełnego importu danych.

Zestawiamy sharding

Naszym celem jest takie zmodyfikowanie konfiguracji DIH by każda instancja indeksowała tylko „swoją” część danych. Najprościej zrobić to modyfikując zapytanie pobierające dane np w ten sposób:

SELECT * from albums where id % LICZBA_INSTANCJI = NUMER_INSTANCJI

gdzie:

  • LICZBA_INSTANCJI – liczba serwerów SOLR przechowujących unikalne części zbioru danych
  • NUMER_INSTANCJI – numer instancji (liczony od zera)

takie zapytanie nie gwarantuje nam dokładnie i idealnie równego podziału ale spełnia dwa konieczne warunki:

  • dany rekord trafi zawsze na konkretną i zawszę tę samą instancję
  • pojedynczy rekord trafi zawsze na tylko jedną instancję

czyli db-data-config.xml na każdej maszynie różni się teraz zapytaniem i wygląda na poszczególnych instancjach następująco:

  • SELECT * from albums where id % 3 = 0
  • SELECT * from albums where id % 3 = 1
  • SELECT * from albums where id % 3 = 2

Sprawdzamy działanie

Po uruchomieniu wszystkich instancji SOLR na każdej wywołujemy adres:

/solr/dataimport?command=full-import

Po zakończeniu pracy DIH i wywołaniu:

/solr/dataimport?command=status

dostajemy w odpowiedzi od instancji odpowiednio:

  • Added/Updated: 275220 documents.
  • Added/Updated: 275221 documents.
  • Added/Updated: 275220 documents.

Wykonując prostą operację dodawania widzimy, że we wszystkich instancjach łącznie mamy 825661 dokumentów, czyli tyle ile powinno tam być 🙂
Wykonajmy jeszcze zapytanie o wszystkie dokumenty, z wykorzystaniem shardingu wywołując na dowolnej instancji:

/solr/select/?q=*:*&shards=localhost:6761/solr,localhost:7872/solr,localhost:8983/solr

Wynik: 825661.

To działa! 🙂

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

We use cookies to personalise content and ads, to provide social media features and to analyse our traffic. We also share information about your use of our site with our social media, advertising and analytics partners. /home/aludstro/domains/solr.pl/public_html/wp-includes/link-template.php on line 409
https://solr.pl/data-import-handler-sharding/">View more
Cookies settings
Accept
Privacy & Cookie policy
Privacy & Cookies policy
Cookie name Active
Save settings
Cookies settings