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 e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *