Posty oznaczone etykietą elasticsearch

ElasticSearch 6 - na dobrej drodze

Wersja 6

Wersja 6.0 ElasticSearch jest dla mnie szczególna - twórcy wprowadzają zmiany ułatwiające zarządzanie, ale też rezygnują z dawnych błędów, które krytykowałem na łamach tego bloga.

Każdemu polecam migrację do wersji 6.x. Służę pomocą w migracji z wersji 2.x oraz 5.x.

Aktualizacje ElasticSearch - jak wykonać?

Nie można zaprzeczyć, że ElasticSearch jest rozwijany dynamicznie. Tak szybki rozwój produktu nie zawsze jest oczekiwany, bo albo wdrożenie zostaje (z przyczyn obiektywnych) oparte o zamrożoną (i nie wspieraną) wersję, albo konieczne staje się przeprowadzanie migracji do nowszych wersji. Takie operacje trzeba zaplanować, zabudżetować, a na dodatek nie obejdzie się bez downtime i sukcesem jest, gdy przerwa techniczna jest relatywnie krótka.

Przypomnę w tym miejscu daty końca wsparcia poszczególnych wersji ElasticSearch:

Elasticsearch EOL Date Maintained Until
2.0.x 2017-04-28 2.1.0
2.1.x 2017-05-24 2.2.0
2.2.x 2017-08-02 2.3.0
2.3.x 2017-09-30 2.4.0
2.4.x 2018-02-28 6.0.0
5.0.x 2018-04-26 5.1.0
5.1.x 2018-06-08 5.2.0
5.2.x 2018-07-31 5.3.0
5.3.x 2018-09-28 5.4.0
5.4.x 2018-11-04 5.5.0
5.5.x 2019-01-06 5.6.0
5.6.x 2019-03-11 7.0.0
6.0.x 2019-05-14 6.1.0
6.1.x 2019-06-13 6.2.0
6.2.x 2019-08-06 6.3.0
6.3.x 2019-12-13 6.4.0
6.4.x 2020-02-23 6.5.0
6.5.x 2020-05-14 6.6.0
6.6.x 2020-07-29 6.7.0
6.7.x 2020-09-26 8.0.0
7.0.x 2020-10-10 7.1.0

Przygotowując się do jakichkolwiek operacji powinno się opracować procedurę, z którą należy zapoznać wszystkich zainteresowanych, opracować procedurę odwrotną, tj. wycofującą zmiany w razie nieprzewidzianych problemów, albo oznaczyć jasno punkty po realizacji których nie ma już odwrotu.

W przypadku ElasticSearch procedura jest o tyle bezpieczna, że ryzyko utraty danych jest stosunkowo niewielkie i ogranicza się do przypadku utraty danych z kartoteki wtórnej (zazwyczaj bazy danych RDBMS systemu OLTP), co ma miejsce niezwykle rzadko ale jest możliwe (a jak coś jest możliwe, to zazwyczaj dzieje się w najgorszym momencie).

Czy można śmiało aktualizować ElasticSearch? Tak, ale pod warunkiem, że został zapewniony backup danych lub środowiska. Największym problemem jest downtime, czyli czas braku usługi, który będzie skutkował wyłączeniem bądź dysfunkcją aplikacji web.

A czy warto aktualizować? Tak!

Aktualizacja od 5.x

Producent zapewnia, że aktualizacja od wersji 5.6.3 nie wymaga downtime. Zachowanie kompatybilności wstecznej na poziomie fizycznym jest ogromnym plusem tego wydania.

Wyjątkiem jest użycie X-Pack Security bez SSL/TLS, co wymaga przekonfigurowania węzłów (włączenia SSL/TLS) i restartu całego klastra. Pomijam przypadki, gdzie w stacku używana jest np. Kibana i najlepiej użyć jest asystenta migracji.

Etapy migracji warto zatem podzielić na: - migrację 2.x do 5 - migrację 5.x do 5.6.3 - migrację 5.6.3 do 6.x

Koniec z mappingami

Nie mogę powiedzieć, że to mój osobisty sukces, ale wersja 6.0 wycofuje tzw. mappingi, czyli grupowanie atrybutów w bliżej nieokreślonym celu. O bezsensie mappingów pisałem szerzej we wpisie z 2016 roku.

Dzięki temu posunięciu indeksy są w końcu takie, jakie powinny być. Tworzenie bibliotek klienckich też staje się o prostsze (dokładnie o jedną warstwę), gdyż struktura indeksu nie musi być opisywana wieloma mappingami. Wydajność takich indeksów staje się lepsza, a zarządzanie nimi - prostsze.

ElasticSearch 6.x zachowuje kompatybilność pozostawiając obsługę mappingów w starych indeksach, sam ogranicza tworzenie dokładnie jednego mappingu do indeksu, aż w wersji 7.0 mappingi zostaną kompletnie usunięte (z wyjątkami w 9.0).

Twórcy ElasticSearch argumentują zmiany takimi słowami:

In the early days of Elasticsearch, we spoke about an “index” being similar to a “database” in an SQL database, and a “type” being equivalent to a “table”. This was a bad analogy that led to incorrect assumptions. In an SQL database, tables are independent of each other. The columns in one table have no bearing on columns with the same name in another table. This is not the case for fields in a mapping type.

Tak. Ta analogia była po prostu głupia.

In an Elasticsearch index, fields that have the same name in different mapping types are backed by the same Lucene field internally. In other words, using the example above, the user_name field in the user type is stored in exactly the same field as the user_name field in the tweet type, and both user_name fields must have the same mapping (definition) in both types.

I dokładnie to krytykowałem w moim poprzednim wpisie.

Cieszę się, że twórcy ElasticSearch w końcu to dostrzegli. Czekam, aż przyjmą do wiadomości, że ich API HTTP/JSON nie jest RESTful :)

Co nowego w ElasticSearch 6.0?

Wersja 6.0, oprócz pierwszych kroków do usunięcia naprawdę głupich mappingów, poprawia wydajność wyszukiwania, szczególnie skracając czasy wyszukiwania posortowanych zbiorów, ale też usprawnia w wyszukiwanie rozproszone oraz bezpieczeństwo.

To pierwsza wersja ElasticSearch, do której gorąco namawiam obecnych i potencjalnych klientów. Zainteresowanych proszę o kontakt przez stronę firmową lub telefonicznie +48326100016.

ElasticSearch nie taki elastic

Oryginalny tekst datowany jest na 4.11.2015, a uzupełniony w lipcu 2016

ElasticSearch jest takim samym systemem wyszukiwania, jak każdy inny powstały w przeciągu ostatnich kilkudziesięciu lat. Indeks ma sztywną strukturę i nic tego nie zmieni. Jedyna różnica polega na tym, że tenże indeks jest modyfikowany w locie / w tle, co niesie za sobą sporo, czasem przykrych konsekwencji, choć na początku może wydawać się to świetnym pomysłem.

Nie-typy, czyli "mappingi"

ElasticSearch posiada tzw. "mappingi". Niektórzy mogą uważać, że są to typy indeksowanych dokumentów. Słowo "typ" z resztą pada w dokumentacji. Ale to nie są typy. Są to elementy grupujące kolumny indeksu w pewne logiczne klasy, które mogą posłużyć jako dodatkowy filtr lub zbiór definicji o analizerach i tokenizerach, oraz mogą mieć znaczenie wydajnościowe (operujemy na jakimś podzbiorze). Można je porównać do widoków znanych z RDBMS.

Należy jednak pamiętać, że kolumny (tudzież pola) w "mappingach" należą do zbioru kolumn (pól) całego indeksu. Zatem kolumny o tych samych nazwach, mimo że należą do różnych "mappingów", muszą być tego samego typu. I mimo że interfejs ElasticSearch umożliwia rozłączne definiowanie "mappingów", to próba użycia tej samej nazwy z różnymi typami spowoduje wygenerowanie błędu.

Efektem ubocznym nieuważnego stosowania mappingów są przerośnięte i niewydajne indeksy. Istnieje zalecenie niemodyfikowania "mappingów", lub ich bardzo rzadkiego modyfikowania.

Plusy? Może jakieś są, ale jestem zwolennikiem rozłącznych indeksów (z powodów wydajnościowych i architektonicznych) wraz z multiindex query.

Nie-dynamiczna struktura

Tu należy wrócić do udawanego dynamizmu ElasticSearch. Otóż dodanie pierwszego dokumentu o niby-dowolnej strukturze powoduje automatyczne rozszerzanie mappingu, indeksu, oraz zgadywanie typu kolumny (pola). To pierwszy krok do problemów z mappingami i typami, które jeśli zostaną zaniedbane mogą kończyć się żmudnym maintenance indexu a w najgorszym razie jego całkowitym usunięciem oraz zasileniem od nowa po wprowadzeniu zmian.

Podczas dynamicznego mappingu typ pola jest określany na bazie pierwszej indeksowanej wartości tego pola. Z tego wynika, że w niektórych przypadkach to los określa, kiedy nastąpi awaria - wystarczy indeksować dokumenty w nieokreślonej kolejności. A oddawanie działania systemów w ręce losu jest skrajnie nieodpowiedzialne.

Nie-RESTful API

Innym ważnym aspektem jest fakt, iż ElasticSearch nie posiada RESTful API. Autorzy mylnie lub z powodów marketingowych używają tego określenia. ElasticSearch posiada API oparte o HTTP i dokumenty JSON, ale nie jest to interfejs RESTful, przez co jest nieintuicyjny i bez dokumentacji nie da się go "konsumować". Sens interfejsu RESTful dla Elastica jest raczej znikomy, wprost przeciwnie do marketingu.

Natomiast same kwerendy JSON, mimo że potrafią być skomplikowane, są bardzo elastyczne. Wiele poziomów zagnieżdżania JSON utrudnia czytanie i pisanie kwerend, ale najważniejsza jest ich skuteczność. Zapytać można praktycznie o wszystko, także za pomocą własnych skryptów.

Skalowalność

Na koniec zwrócę uwagę na fakt, że ElasticSearch jest silnikiem skalowalnym. Oznacza to, że jego instalacja jest tożsama z wdrożeniem pewnego rodzaju klastra. Bez przemyślenia architektury tego klastra i odpowiednich kroków związanych z jego deploymentem, narażamy się na potencjalnie dużą awarię systemu, łącznie z utratą danych.

Należy także zwrócić uwagę na (write/read) consistency level. Są to parametry często występujące przy zapisie i odczycie danych. Ich nieprawidłowe użycie (w stosunku do wdrożonego klastra) może skutkować utratą danych lub ich niespójnością.

Język polski

ElasticSearch nie wspiera natywnie j. polskiego, ale istnieje do niego plugin do analizy leksykalnej - Stempel, który jest rozszerzeniem silnika Lucene.

https://github.com/elastic/elasticsearch-analysis-stempel

Podsumowanie

ElasticSearch jest ciekawym narzędziem, prostszym w konfiguracji i pierwszej instalacji niż Apache SOLR, jednakże należy używać go z głową, ostrożnie, i najlepiej unikać "dynamizmu" poprzez skrupulatną walidację danych wejściowych w części klienckiej.

Żałuję, że walidacji danych wejściowych nie robi sam silnik, tak jak to miało miejsce w przypadku Apache SOLR. Ta odpowiedzialność została przeniesiona na klienty, a w praktyce na programistów. A ponieważ nie da się wszystkiego przewidzieć, to bezrefleksyjne użycie Elastica może skończyć się nieprzewidzianą katastrofą działającego systemu.

ElasticSearch nie dysponuje narzędziami typu "DataSource". W Apache SOLR można było zdefiniować źródło danych będące zwykłym SQL-em, co umożliwiało budowanie optymalnych kwerend i zasilanie indeksu bez rozbudowywania warstwy aplikacji klienta. I choć nie zawsze jest to wygodne, to w wielu przypadkach wystarczało, oraz miało jedną istotną zaletę - zawsze działało.

ElasticSearch posiada biblioteki dla wielu języków programowania. Biblioteki dla Pythona są względnie kiepskie poza oficjalną-podstawową, która jest już dosyć rozwinięta lecz nie wolna od wad. Ponieważ odpowiedzialność za błędy mappnigów została przeniesiona na klienty, to jako programista potrzebuję biblioteki, która uniemożliwi lub utrudni mi strzelenie sobie w stopę.

Wokół ElasticSearch widzę bardzo dużo ciekawych narzędzi. Stał się też bardzo popularny. To są niewątpliwie spore zalety, bo społeczność wydaje się większa niż w przypadku Apache SOLR, i produkt ma lepsze wsparcie. Jednak wyczuwam też sporą dawkę "marketing bullshitu", o którym czuję się zobowiązany wspomnieć.

Myślę jednak, że to nie koniec moich przygód z ElasticSearch. Jak do tej pory wady nie przesłaniają zalet. Nie trzeba grzebać po plikach XML, konfigurować instalacji multicore, ani generować schematów indeksów w XML. Wszystko jest do załatwienia przez HTTP. Biblioteki, choć nieidealne, są i działają. Funkcjonalność silnika jest mocna (wszak to Lucene, tak samo jak w Apache SOLR), oraz jest sharding bez ręcznych robótek z tzw. dekompozycją obiektową.

Uzupełnienie (4.11.2015)

Nowy SOLR

Najnowsza wersja Apache SOLR również wspiera model "schemaless", tj. dynamiczne konstruowanie indeksu. Z tą różnicą, że po "zabawie" developerskiej można przełączyć się na "configured schema", aby zachować stabilność środowiska. Nie bedzie mowy o tym, że ktokolwiek (jakikolwiek klient) przypadkowo czy intencjonalnie "rozwali" indeks.

Do tego nowa wersja zapewnia skalowanie w oparciu o sprawdzony Apache Zookeeper i przedkłada spójność danych ponad inne aspekty, co zapobiega tzw. split brainowi.

Ponieważ mam jakieś tam doświadczenie z Apache SOLR (tyle że starszą wersją), wiem że język zapytań spełnia wszystkie oczekiwania, wsparcie facetingu jest więcej niż poprawne, wpływ na indeksowanie mam praktycznie nieograniczony, dostaję do tego stabilność oraz gwarancję spójności danych, a teraz jako bonus łatwiejszy sposób konstruowania indeksu, to najprawdopodobniej pozostanę zwolennikiem SOLR-a. Jest to produkt starszy i bardziej dojrzały, oraz nie sterowany sprzedażą i marketingiem. Mniej popularny? Python też jest mniej popularny. I całe szczęście.

Porównanie

Znalazłem przed chwilą porównanie SOLR z ElasticSearch: http://www.datanami.com/2015/01/22/solr-elasticsearch-question/

Polecam przeczytać.

Oprócz technicznych różnic istnieją nieco odmienne cele oraz podejście do open-source. W skrócie:

  • SOLR jest nakierowany na Full Text Search, ElasticSearch głównie na filtrowanie i agregacje
  • SOLR jest prawdziwym open-source budowanym przez community, Elastic rozwija jedna firma i jej pracownicy, którzy decydują o kierunku rozwoju
  • SOLR opiera się o Apache Zookeeper, co daje pewną gwarancję, lecz także trudność we wdrożeniu; ElasticSearch z kolei jest prostszy we wdrażeniu klastra, lecz cierpi na różne problemy "wieku dziecięcego" związanego ze spójnością danych
  • Wydajność obu jest porównywalna
  • Wsparcie obu jest porównywalne

Oraz ważne wg mnie:

  • SOLR umożliwia przełączenie się na klasyczną "sztywną" strukturę (wyłączenie pseudo-dynamizmu), co jest ważne dla utrzymania stabilności
  • SOLR dostarcza dodatkowe narzędzia pomocne przy konstruowaniu systemów wyszukiwania
  • SOLR nie przenosi odpowiedzialności za poprawność danych oraz wydajność indeksu na klienty

Uzupełnienie (12.07.2016)

ElasticSearch 2.x oferuje bogate możliwości wyszukiwania i indeksowania geospatial, z którego zaczynam korzystać w jednym z projektów. Mimo wspomnianych wcześniej wad decyduję się po raz kolejny na ElasticSearch, lecz z całą świadomością i należytą ostrożnością.

Awaria

Znajduję ponad to w sieci historię fuckupu systemu live spowodowanego przez Elastic, właśnie z powodów opisywanych wcześniej. Awaria nastąpiła niecały miesiąc po napisaniu przeze mnie pierwszej wersji tekstu. Oczywiście te dwie sprawy związku ze sobą nie mają, ale ciśnie mi się na usta klasyczne "a nie mówiłem?"

Wyłączanie zgaduj-zgaduli

Zalecam wyłączenie automatycznego mappingu, za który odpowiada parametr w elasticsearch.yml:

"index.mapper.dynamic": false

Nie można jednak zagwarantować, że jest to w 100% skuteczne w każdej wersji Elastica, bo znany jest błąd: https://github.com/elastic/elasticsearch/issues/15381

Można także wyłączyć automatyczne tworzenie indeksu:

"action.auto_create_index": false

Ostrożnej zabawy!