Solr 4.3: Dzielenie shard’ów – szybkie spojrzenie

Wraz z wersją 4.3 serwera wyszukiwania Apache Solr dostaliśmy bardzo długo oczekiwaną funkcjonalność – możliwość dzielenia części kolekcji kiedy korzystamy z wdrożenia opartego o SolrCloud. W tym wpisie chcieliśmy wypróbować nową funkcjonalność i zobaczyć jak działa. Do dzieła więc.

Kilka słów na początek

Wybór odpowiedniej liczby części z jakich będzie składała się nasza kolekcja był do tej pory jedną z niewiadomych, których wartość musieliśmy znać przed wdrożeniem. Kiedy tylko stworzyliśmy kolekcję nie mogliśmy zmienić liczby shardów z jakich się składa, mogliśmy dodawać tylko nowe repliki. Oczywiście niosło to za sobą konsekwencje – jeżeli nasze zalożenia nie były prawidłowe mogło się okazać, iż liczba shardów jest niewystarczająca. Mogliśmy wtedy tylko zalożyć nową kolekcję z inną konfiguracją, a następnie przeindeksować dane. Aż do chwili, kiedy pojawił się Apache Solr 4.3, a wraz z nim możliwość dzielenia na części stworzonej już kolekcji.

Mały klaster

W celu przetestowania nowej funkcjonalności postanowiłem uruchomić klaster składający się z jednej instancji Solr oraz z wbudowanym ZooKeeperem oraz przykładową kolekcją dostarczaną wraz z Solr. W tym celu użyłem następującej komendy:

java -Dbootstrap_confdir=./solr/collection1/conf -Dcollection.configName=collection1 -DzkRun -DnumShards=1 -DmaxShardsPerNode=2 -DreplicationFactor=1 -jar start.jar

Po uruchomieniu Solr widok klastra przedstawiał się następująco:

after_start

Testowe dane

Do testów potrzebne są także jakieś dane, postanowiłem więc skorzystać z przykładowych dostarczanych z Solr i uruchomić następujące polecenie w katalogu exampledocs:

java -jar post.jar *.xml

Liczbę zaindeksowanych dokumentów sprawdzić można wykonując następującą komendę:

curl 'http://localhost:8983/solr/collection1/select?q=*:*&rows=0'

Na którą Solr odpowiedział następująco:

<?xml version="1.0" encoding="UTF-8"?>
<response>
<lst name="responseHeader">
  <int name="status">0</int>
  <int name="QTime">5</int>
  <lst name="params">
    <str name="q">*:*</str>
    <str name="rows">0</str>
  </lst>
</lst>
<result name="response" numFound="32" start="0">
</result>
</response>

Jak widać zaindeksowanych zostało dokładnie 32 dokumenty.

Podział shard’a

Spróbujmy zatem podzielić nasz pojedynczy shard, z którego składa się nasza kolekcja. W tym celu wykorzystamy API kolekcji i nową akcję o nazwie SPLITSHARD, która w podstawowej wersji przymuje dwa parametery – collection, czyli nazwę kolekcji na której chcemy wykonać operację oraz shard, czyli nazwę shard’a którego chcemy podzielić. W naszym wypadku komenda, która podzieli kolekcję jest następująca:

curl 'http://localhost:8983/solr/admin/collections?action=SPLITSHARD&collection=collection1&shard=shard1'

Po chwili, jeżeli wszystko przebiegło poprawnie, powinniśmy dostać od Solr odpowiedź informującą o przebiegu operacji podziału, wyglądającą mniej więcej tak:

<?xml version="1.0" encoding="UTF-8"?>
<response>
<lst name="responseHeader">
  <int name="status">0</int>
  <int name="QTime">9220</int>
</lst>
<lst name="success">
  <lst>
    <lst name="responseHeader">
      <int name="status">0</int>
      <int name="QTime">6963</int>
    </lst>
    <str name="core">collection1_shard1_1_replica1</str>
    <str name="saved">/home/solr/4.3/solr/solr.xml</str>
  </lst>
  <lst>
    <lst name="responseHeader">
      <int name="status">0</int>
      <int name="QTime">6977</int>
    </lst>
    <str name="core">collection1_shard1_0_replica1</str>
    <str name="saved">/home/solr/4.3/solr/solr.xml</str>
  </lst>
  <lst>
    <lst name="responseHeader">
      <int name="status">0</int>
      <int name="QTime">9005</int>
    </lst>
  </lst>
  <lst>
    <lst name="responseHeader">
      <int name="status">0</int>
      <int name="QTime">9006</int>
    </lst>
  </lst>
  <lst>
    <lst name="responseHeader">
      <int name="status">0</int>
      <int name="QTime">103</int>
    </lst>
  </lst>
  <lst>
    <lst name="responseHeader">
      <int name="status">0</int>
      <int name="QTime">1</int>
    </lst>
    <str name="core">collection1_shard1_1_replica1</str>
    <str name="status">EMPTY_BUFFER</str>
  </lst>
  <lst>
    <lst name="responseHeader">
      <int name="status">0</int>
      <int name="QTime">1</int>
    </lst>
    <str name="core">collection1_shard1_0_replica1</str>
    <str name="status">EMPTY_BUFFER</str>
  </lst>
</lst>
</response>

Wygląd klastra po podziale

Po podziale nasz klaster wygląda następująco:

after_splitJak widać powstały dwa nowe shardy, które teoretycznie powinny zawierać dokumenty z shard1 – część z dokumentów powinny trafić do części oznaczonej shard1_1, a część do shard1_0. Ponownie korzystając z panelu administarcyjnego Solr możemy sprawdzić odpowiednie core’y:

Shard1_1

Statystki cześci kolekcji oznaczonej jako Shard1_1 wyglądają następująco:

shard_1_1

Shard1_0

Natomiast statystki cześci kolekcji oznaczonej jako Shard1_0 wyglądają następująco:

shard_1_0

Jak widać z 32 dokumentów, które były dostępne w oryginalnej części kolekcji powstały dwie części kolekcji – jedna przechowująca 18 dokumentów,  a druga przechowująca 14 dokumentów. Teoretycznie się zgadza 🙂

Porządki

Na sam koniec zostawiłem sobie porządki. Po pierwsze, aby dane w nowych shardach były widoczne musimy wysłać polecenie commit do naszej kolekcji, np w następujący sposób:

curl 'http://localhost:8983/solr/collection1/update' --data-binary '<commit/>' -H 'Content-type:application/xml'

Możemy także usunąć oryginalny shard z kolekcji, korzystając np. z panelu administracyjnego Solr lub też używając CoreAPI.

Ostatni test

Jako podsumowanie postanowiłem sprawdzić, czy na pewno dokumenty są dostępne w odpowiednich częściach kolekcji. W tym celu skorzystałem z następującego polecenia:

curl 'http://localhost:8983/solr/collection1/select?q=*:*&rows=100&fl=id,[shard]&indent=true'

Odpowiedź Solr na powyższe zapytanie była następująca:

<?xml version="1.0" encoding="UTF-8"?>
<response>
<lst name="responseHeader">
  <int name="status">0</int>
  <int name="QTime">7</int>
  <lst name="params">
    <str name="fl">id,[shard]</str>
    <str name="q">*:*</str>
    <str name="rows">100</str>
  </lst>
</lst>
<result name="response" numFound="32" start="0" maxScore="1.0">
  <doc>
    <str name="id">GB18030TEST</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_0_replica1/</str></doc>
  <doc>
    <str name="id">IW-02</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_0_replica1/</str></doc>
  <doc>
    <str name="id">MA147LL/A</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_0_replica1/</str></doc>
  <doc>
    <str name="id">adata</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_0_replica1/</str></doc>
  <doc>
    <str name="id">asus</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_0_replica1/</str></doc>
  <doc>
    <str name="id">belkin</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_0_replica1/</str></doc>
  <doc>
    <str name="id">maxtor</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_0_replica1/</str></doc>
  <doc>
    <str name="id">TWINX2048-3200PRO</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_0_replica1/</str></doc>
  <doc>
    <str name="id">VS1GB400C3</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_0_replica1/</str></doc>
  <doc>
    <str name="id">VDBDB1A16</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_0_replica1/</str></doc>
  <doc>
    <str name="id">USD</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_0_replica1/</str></doc>
  <doc>
    <str name="id">GBP</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_0_replica1/</str></doc>
  <doc>
    <str name="id">3007WFP</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_0_replica1/</str></doc>
  <doc>
    <str name="id">EN7800GTX/2DHTV/256M</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_0_replica1/</str></doc>
  <doc>
    <str name="id">SP2514N</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">6H500F0</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">F8V7067-APL-KIT</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">apple</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">ati</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">canon</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">corsair</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">dell</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">samsung</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">viewsonic</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">EUR</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">NOK</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">VA902B</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">0579B002</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">9885A004</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">SOLR1000</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">UTF8TEST</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
  <doc>
    <str name="id">100-435805</str>
    <str name="[shard]">192.168.56.1:8983/solr/collection1_shard1_1_replica1/</str></doc>
</result>
</response>

Jak widać dokumenty pochodzą z obu nowych shardów, czyli znów widać, że wszystko się zgadza. Do samego tematu podziału kolekcji na pewno jeszcze wrócimy.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Wymagane pola są oznaczone *