CouchDB/1

Jeśli kogoś zainteresował poprzedni post, a jeszcze nie zainstalował, to poniżej znajduje się mały helper.

Opis dotyczy CouchDB w wersji 0.8.1

Ubuntu 8.04

Potrzebne będzie trochę narzędzi i bibliotek:

sudo apt-get install automake autoconf help2man checkinstall
sudo apt-get install libtool subversion-tools build-essential libreadline5-dev
sudo apt-get install libicu38 libicu-dev
sudo apt-get install erlang

Następnie trzeba zainstalować silnik JS SpiderMonkey, który standardowo wykorzystywany jest przez CouchDB do wykonywania funkcji map i reduce.

sudo apt-get install libmozjs-dev

Oczywiście trzeba także pobrać CouchDB. Po ściągnięciu i rozpakowaniu wchodzimy do katalogu ze źródłami, aby rozpocząć budowanie.

tar -xzvf apache-couchdb-0.8.1-incubating.tar.gz
cd apache-couchdb-0.8.1-incubating
./configure
make && sudo make install

Następnie możemy utworzyć użytkownika, z którego będziemy uruchamiać, nadać odpowiednie prawa itd.

sudo adduser couchdb
sudo mkdir -p /usr/local/var/lib/couchdb
sudo chown -R couchdb /usr/local/var/lib/couchdb
sudo mkdir -p /usr/local/var/log/couchdb
sudo chown -R couchdb /usr/local/var/log/couchdb
sudo mkdir -p /usr/local/var/run
sudo chown -R couchdb /usr/local/var/run

Na zakończenie pozostaje nam wrzucenie skryptu startowego w odpowiednie miejsce:

sudo cp /usr/local/etc/init.d/couchdb /etc/init.d/
sudo update-rc.d couchdb defaults
sudo /etc/init.d/couchdb start

Ubuntu 8.10 Tu ponoć jest już łatwiej…

sudo apt-get install couchdb

…i to by było na tyle.

Mac OS X

Na maku jest trochę prościej niż na Ubuntu 8.04, ale nie aż tak prosto jak na 8.10 ;)

sudo port install couchdb +server

MacPorts zadba o zainstalowanie wszystkich zależności. Pozostaje nam jeszcze nakarmienie LaunchDeamon’a odpowiednim plikiem plist:

sudo launchctl load -w /opt/local/Library/LaunchDaemons/org.apache.couchdb.plist

Plik wskazany przez porty podczas instalacji może nie działać.

Po odpaleniu bazy:

sudo couchdb -b

Jakby ktoś marzył o binarce na maka to mam dobrą/złą (niepotrzebne skreślić) wiadomość. Dla Leoparda na Intelu dostępny jest CouchDBX.

Po instalacji

Otwieramy przeglądarkę i wchodzimy na http://127.0.0.1:5984/_utils/ Powinniśmy zobaczyć:


Możemy odpalić testy, aby sprawdzić czy nasza instalacja działa poprawnie:


Jeśli odpaliliśmy CouchDB w konsoli, to łatwo możemy zaobserwować RESTowe żądania (GET, POST, PUTDELETE):


CouchDB/0

Image CouchDB, czyli baza danych zorientowana na dokumenty, całkowicie schema-free i co za tym wszystkim idzie, pozbawiona relacji. Napisana w Erlangu, języku współbierznym, dzięki czemu z łatwością może efektywnie wykorzystać wszystkie rdzenie procesora(ów). Komunikacja odbywa się via RESTful HTTP/JSON API. Obsługuje także replikację z dwu kierunkowym wykrywaniem i rozwiązywaniem konfliktów.

buzz… buzz…

Jak to widać na uroczym obrazku na stronie CouchDB, bebechy można podzielić na silnik “widoków”, storage i replikacje. Pisząc o widokach należy wspomnieć, że nasza znajomość SQL-92 i pochodnych nie zda się na nic. Nie ma klasycznych zapytań, zamiast tego stosowana jest metoda MapReduce. Funkcje map i reduce piszemy w JavaScripcie, ale tak naprawdę można dodać obsługę funkcji w dowolnym języku (o tym za chwilę). Na temat samego MapReduce można wiele napisać, dlatego nie będę w tej chwili rozwijał tego tematu. Zainteresowanych odsyłam do Wikipedii i, na przykład, tego wpisu.

Dane…

…przechowywane są w postaci zserializowanej do JSON’a. Każdy dokument posiada unikalny ID oraz, co ciekawe, numer rewizji. Jest on wykorzystywany do rozwiązywania konfliktów przy replikacji. Ponad to, dokumenty nie są nadpisywane — zamiast tego tworzone są nowe dokumenty, z nowymi numerami rewizji. Powoduje to, co prawda, rozrastanie się bazy jednak starych rekordów można się łatwo pozbyć (opcja “Compact”). Poza rozwiązywaniem konfliktów, dopisywania zamiast nadpisywania ma jeszcze jeden, poważny plus — brak locków. Przy czytaniu z bazy nigdy nie musimy czekać, aż zakończy się dodawanie czy modyfikacja dokumentów.

Wyciąganie wyników…

…odbywa się poprzez wspomniane wcześniej widoki. Jest możliwość tworzenia ich ad-hoc oraz zapisania do bazy i ponownego wykorzystywania w przyszłości. Zapytania ad-hoc zmuszają system do przeszukiwania całego zbioru danych praktycznie za każdym razem, bez użycia indeksów. Z moich, bardzo wstępnych, obserwacji, na małych zbiorach danych, pierwsze zapytanie bywa nawet 10x wolniejsze od kolejnych w serii. Po “rozgrzaniu”, używanie non stop tego samego widoku nie jest problemem. Niestety, taki tymczasowy widok równie szybko “stygnie” i po kilkunastosekundowej przerwie, znów będziemy musieli odczekać swoje. Dlatego preferowane jest używanie widoków, które są zapisane do bazy i podobnie jak dane, replikowane do innych instancji. Po utworzeniu takiego widoku automatycznie budowane są dla niego indeksy. Przy dodawaniu czy modyfikacji danych indeksy są na bieżąco odświeżane. Wyłączenie prądu w trakcie dopisywania do indeksu nie powoduje konieczności jego budowania od nowa po ponownym włączeniu. Aktualizacja powinna zacząć się praktycznie od miejsca w którym została przerwana.

Jak nie JavaScript to…

…praktycznie dowolny język programowania. Jak wspomniałem wcześniej, standardowo piszemy je w JavaScripcie. Do ich obsługi wykorzystywany jest silnik Spider Monkey — osadzony w wielu produktach Mozilli. Gdy zapragniemy zmian wystarczy do konfiguracji dopisać moduł obsługujący funkcje w innym języku. Na nieco ubogim wiki CouchDB znajdziemy opis jak obsłużyć inne języki. Zawiera ona także informacje o wspieranych już językach.

Skalowanie

Dzięki wbudowanym mechanizmom dwu kierunkowej replikacji można myśleć o środowisku rozproszonym. Pomyślcie ile daje dostęp via HTTP. Narzędzi do rozkładania obciążenia na dowolną liczbę maszyn mamy pełno (perlbal, nginx, itd.). Jakby zaszła potrzeba trzymania w pamięci wyników, zawsze można użyć Squida czy Varnisha i nie musimy przy tym ingerować w aplikację. Analiza, jakiego typu “zapytań” jest najwięcej? Nic trudnego, narzędzi do analizy logów serwerów WWW też jest pełno. Zresztą, jakie by te logi nie były Splunk i tak sobie z nimi poradzi.

Tylko po co to wszystko?

Sporo szumu robi się w około denormalizacji danych, partycjonowania, spłaszczania struktury. Ostatecznie wychodzi na to, że bardzo często chcemy uniknąć relacji. Warto się zastanowić czy robienie tego nie jako na siłę ma sens, czy nie lepiej użyć czegoś co w sposób całkowicie naturalny daje nam płaską, dynamiczną strukturę, gdzie denormalizacja jest codziennością. Oczywiście wszystko zależy od konkretnego przypadku i nie można generalizować, że relacyjne bazy są złe, a ich czas dobiega końca.

Coś do poczytania

WebDeveloper i jego safari

Safari jest przyzwoitą przeglądarką, ale zawsze brakowało mi w niej paru bajerów z Firebuga, YSlowa i WebDevelopera.

Okazuje się, że istnieje magiczna komenda, która aktywuje nam kilka ukrytych ficzerów, a wygląda ona tak: defaults write com.apple.Safari IncludeDebugMenu YES

Po jej wpisaniu w terminalu wystarczy zrestartować Safarynę, aby po jej ponownym starcie dostrzec w menu pozycję Develop

Znajdziemy w niej takie rzeczy jak:

  • otwieranie strony we wszystkich przeglądarkach (i nie tylko, bo jeszcze może być VLC, Evernote czy inne aplikacje) jakie mamy zainstalowane
  • zmiana user-agenta na dowolny
  • konsola logów
  • timeline sieciowy ze wszystkimi requestami, szczegółami o nich, hintami co można poprawić, czas transeru, rozmiar, podział tych danych na dokumenty, obrazki, skrypty i pozostałe
  • wyłączanie cache, obrazków, styli, itp.

Do pełni szczęścia brakuje mi tylko Inspect’a z FireBuga, ale nie można przecież mieć wszystkiego. ;)

UPDATE Coś, trochę na kształt inspect’a też jest.

Mini Japko

Jestem szczęśliwym, aczkolwiek trochę marudzącym posiadaczem Mac Mini od kilku dni. Na ogólne uwagi przyjdzie jeszcze pora, ale teraz będzie o pewnej ciekawostce.

Problem był natury takiej, że chciałem zmusić Finder’a do wyświetlania miniaturek fotek, które są podlinkowane za pomocą symlinków zwykłych. Chwila przyglądania się aliasom w Finderze doprowadziła nas do czegoś dziwnego. Czym on właściwie jest? Jeśli patrzymy na niego z Findera, to nie jest niczym ciekawym, ale inaczej jest w konsoli, gdzie okazuje się, że to zwykły plik. Skoro to plik, to można do niego coś wpisać i zobaczyć co się z nim stanie.

O dziwo, dalej da się kliknąć w alias i będziemy w dobrym miejscu. Skoro tak, to zróbmy obraz .dmg i wykonajmy na nim cat przekazując zawartość do pliku reprezentującego nasz alias. W Finderze nadal wszystko jest ok, więc pozostaje nam już tylko zamontowanie z konsoli naszego aliasa jako obrazu.

W ten sposób możemy chować muzykę, wideo, cokolwiek.

Ot, taka ciekawostka ;)

Autocompletery

W życiu każdego przychodzi kiedyś taki moment, że trzeba zrobić coś wbrew sobie. Na przykład skodować coś w JS. Pocieszeniem, może być fakt, iż zawsze gorzej może być — jest jeszcze flash. A fu!

Zmagania z autocomplete do formularzy zostały rozpoczęte.

Wymagania:

  • musi działać bez patchowania bibliotek, frameworków i okolic
  • musi mieć możliwość wysłania requesta z co najmniej dwoma parametrami (np. szukany ciąg znaków i ID miasta)
  • musi jadać output w JSON’ie
  • obsługa parsowania danych zwróconych z serwera musi być dość elastyczna

Pod lupę poszły kolejno: MochiKit, Scriptaculous i Yahoo UI

MochiKit jest spory, ma własny namespace i nie modyfikuje natywnych obiektów więc nie byłoby problemów z dołożeniem do istniejących skryptów. Jest modułowy i ma pokaźną ilość bajerów. Sęk w tym, że na dobrą sprawę jak chcemy czegoś użyć to okazuje się, że ma takie zależności, iż wszystkie moduły i tak zostaną zaimportowane. I jak się okazuje nie posiada w oficjalnej paczce autocomplete. Jedynie na ich wiki jest port skryptu ze Scriptaculous. Port, portem, a bugi, bugami. Użyć tego się nie dało bez wnikania w kod i dochodzenia się warum działać nie chce. Inna wada, to to, że jest to port czegoś co poszło jako następne pod lupę.

Scriptaculous, do działania wymaga dodatkowo prototype, więc też już się tego robi sporo. Autocomplete jest, jednak…. nie znalazłem nigdzie opcji, aby przekazać 2 parametry do serwera. Samo to, wystarczyło, aby skreślić Scriptaculous z listy. Oliwy do ognia dodał fakt, iż ten autocomplete oczekiwał, że dostanie ode mnie zwykłą html’ową listę. Może jeszcze tosty z serem i oregano dla smaku?

Zostało do zbadania Yahoo. Trzeba przyznać, że dokumentację mają całkiem sensowną. Plus dla nich za to. Yahoo ma swój namespace, a ponad to nie modyfikuje (ponoć) obiektów JS’owych, czyli kwalifikuje się do użycia w projekcie, gdzie jakieś skrypty wykorzystujące inne frameworki już są. Ichnie autocomplete potrafi wysłać w zasadzie dowolną ilość parametrów. Sęk w tym, że nie potrafi tego dokonać metodą POST. Pierwszy parametr wyciągnięty z elementu o podanym ID poleci GET’em jako “query”. O kolejne musimy sami się zatroszczyć i przekazać je do odpowiedniej metody w obiekcie requestu ajaxowego. Kolejnym plusem i to nawet całkiem sporym jest sposób w jaki obsługuje zwracane dane w JSON’ie. Na dobrą sprawę Autocomplete od Yahoo powinien móc obsłużyć dowolnie zamotane struktury.. Ponad to, daje możliwość w całkiem przyjemny sposób dać coś a’la google suggest, czyli np. przy każdej pozycji liczbę wyników, osób będących w jakimś mieście — cokolwiek co zechcemy.. ;)