Cassandra a PHP - Twissandra

V předchozím článku jsem se věnoval obecně konfiguraci a spuštění Cassandry (více uzlů na jednom stroji), tentokrát bych se rád prezentoval svoje zkušenosti s přístupem ke Cassandře z PHP. Cassandra je často demonstrována na Twissandře, schématu určeném jakoby pro Twitter, a toto schéma bude pro jednoduchost použito i v tomto článku ...

Tento článek je určitým pokračováním článku Cassandra By Example, ve kterém Eric Evans představuje základní principy Cassandry (co jsou to keyspaces, column families apod. mimo jiné v kontrastu s relačním schématem) právě na Twissandře, a ukazuje jak je Cassandře přistupovat z Pythonu (pomocí knihovny pycassa).

Nemám v úmyslu odkazovaný článek jakkoliv vykrádat nebo zbytečně duplikovat - rád bych aktualizoval některé informace (pro Cassandru 0.7.x) a doplnil informace o přístupu z PHP. Rozhodně doporučuji k přečtení první polovinu Ericova článku, tj. odstavce "Twitter" (představující relační schéma pro Twitter) a "Twissandra" (ukazující odpovídající schéma v Cassandře).

Vytvoření schématu

Jak už jsem zmínil, článek Erica Evanse byl psán pro Cassandru 0.6, což mimo jiné znamená že struktura databáze (keyspaces, column families) byla deklarována pomocí XML souboru. To se ve verzi 0.7 změnilo, protože XML bylo defacto elimimováno a schéma se definuje přímo v databázi pomocí rozhraní cassandra-cli. Spusťte tedy cassandra-cli a vytvořte strukturu pro Twissandru:

create keyspace Twissandra;

use Twissandra;

create column family User      with comparator = UTF8Type;
create column family Username  with comparator = BytesType;
create column family Friends   with comparator = BytesType;
create column family Followers with comparator = BytesType;
create column family Tweet     with comparator = UTF8Type;
create column family Userline  with comparator = LongType;
create column family Timeline  with comparator = LongType;

Vysvětlení obecných pojmů keyspace a column family, stejně jako významu jednotlivých column families, najdete v již dříve zmiňovaném článku.

Knihovna phpcassa

Pro Cassandru existují dvě klientské PHP knihovny - phpcassa a SimpleCassie. Zkoušel jsem obě a osobně rozhodně doporučuji první jmenovanou. SimpleCassie se sice prezentuje jako jednodušší na použití (což je zejména v začátcích lákavé), nicméně dokumentace je naprosto nedostatečná a některé věci se mi ani po dlouhém snažení nepodařilo zprovoznit. Naopak v phpcassa fungovalo vše na první pokus a dokumentace je dosti podrobná. Navíc se jedná o "PHP variantu" knihovny pycassa, takže většinu příkladů z Pythonu lze velmi jednoduše přepsat.

Instalace knihovny je dosti jednoduchá - stačí stáhnout vhodný balíček, rozbalit ho a na začátku skriptu (nebo např. v .htaccess souboru) nastavit odpovídající include_path.

Připojení ke Cassandře a inicializace

První co je třeba udělat je vytvořit spojení ke Cassandře (k jednomu z uzlů) a inicializovat objekty reprezentující jednotlivé column families.

/* nacteni phpcassa knihoven */
require_once('phpcassa/connection.php');
require_once('phpcassa/columnfamily.php');

/* pripojeni ke keyspace Twissandra na IP 10.0.0.1 */
$conn = new ConnectionPool('Twissandra', array('10.0.0.1:9160',
                                               '10.0.0.2:9160',
                                               '10.0.0.3:9160'));

/* inicializace column families */
$user_cf = new ColumnFamily($conn, 'User');
$username_cf = new ColumnFamily($conn, 'Username');
$friends_cf = new ColumnFamily($conn, 'Friends');
$followers_cf = new ColumnFamily($conn, 'Followers');
$tweet_cf = new ColumnFamily($conn, 'Tweet');
$userline_cf = new ColumnFamily($conn, 'Userline');
$timeline_cf = new ColumnFamily($conn, 'Timeline');

a nyní už můžeme implementovat jednodlivé funkce. Nejdříve funkce pro vytvoření uživatele

function create_user($userid, $username, $password) {

    global $user_cf, $username_cf;

    $user_cf->insert($userid, array('id' => $userid,
                                    'username' => $username,
                                    'password' => $password));

    $username_cf->insert($username, array('userid' => $userid));

}

a vytvoření "followera" (uživatel sleduje tweety jiného uživatele)

function add_follower($userid, $friendid) {

    global $friends_cf, $followers_cf;

    $friends_cf->insert($friendid, array($userid => time()));
    $followers_cf->insert($userid, array($friendid => time()));

}

Poslední funkce vytvářející objekty se týká tweetů

function create_tweet($userid, $tweetid, $body) {

    global $tweet_cf, $timeline_cf, $userline_cf, $followers_cf;

    $time = time();

    $tweet_cf->insert($tweetid, array('id' => $tweetid,
                                      'userid' => $userid,
                                      'body' => $body,
                                      '_ts' => $time));

    $userline_cf->insert($userid, array($time => $tweetid));
    $timeline_cf->insert($userid, array($time => $tweetid));

    foreach ($followers_cf->get($userid) AS $fid => $ftime) {
        $timeline_cf->insert($fid, array($time => $tweetid));
    }

}

a nakonec dvě funkce pro načítání dat - vypsání tweetů vložených konkrétním uživatem a načtení tweetů z časové osy uživatele (tj. jeho tweetů a tweetů jeho přátel):

function get_tweets($userid) {

    global $userline_cf, $tweet_cf;

    $timeline = $userline_cf->get($userid);

    return $tweet_cf->multiget($timeline);

}

function get_timeline($userid) {

    global $timeline_cf, $tweet_cf;

    $timeline = $timeline_cf->get($userid);

    return $tweet_cf->multiget($timeline);

}

Tyto funkce pochopitelně nejsou dokonalé a je na nich co zlepšovat (např. použití přesnějšího času než poskytuje funkce time()), eliminace globálních proměnných (které jsou použity pro jednodušší formulaci příkladů), neošetření výjimek např. při nenalezení položky s daným klíčem.

Podrobnější info o použití knihovny phpcassa najdete zde, dokumentaci API zde. Skript s implementací výše uvedeného příkladu (a krátkého případu použití) můžete stáhnout zde.

Komentáře

K tomuto článku zatím žádné komentáře neexistují (nebo čekají na schválení).

Nový komentář

Všechny komentáře podléhají schválení - mezi odesláním komentáře a jeho zobrazením na této stránce tedy může být prodleva. Vyplníte-li e-mailovou adresu, budete o schválení či neschválení komentáře informováni.

V titulku ani v textu nejsou povoleny HTML tagy - budou automaticky odstraněny. Odstavec ukončíte prázdným řádkem.

(nepovinné)