Как стать автором
Обновить

PHP модуль для Tarantool

Время на прочтение6 мин
Количество просмотров6.8K
imageTarantool это разработка компании Mail.ru. Представляет высокопроизводительное key/value no-Sql решение.Отсутствие портов для популярных языков программирования сдерживает популярность данной БД. Попытался восполнить данный пробел.
Ветка экспериментальная. Исходники
Далее примеры.
Немного о самой БД

Tarantool — это распределенное key/value хранилище.
Необходимо отметить, что Tarantool — это хранилище данных, а не система кеширования типа memcache. Все данные находятся в памяти и при необходимости сохраняются в файлах (снапах).

Данное хранилище, в отличие от традиционного memcached & redis хранилища имеет дополнительные возможности:
  • наложение дополнительных индексов на данные
  • индексы могут быть составными
  • индексы могут иметь тип TREE или HASH
  • осуществление выборок по одному или нескольким индексам
  • изъятие данных частями (аналог LIMIT/OFFSET)

Tarantool оперирует данными, которые объединены в неймспейсы (namespace). Неймспейс — это аналог таблицы в MySQL. В системе организована цифровая нумерация неймспейсов (0, 1, 2, 3 ...).
На каждый неймспейс накладывается индекс. Индексы могут накладываться на числовое (int32 или int64) или символьное поле. Как упоминалось выше: индексы могут быть двух типов: HASH & TREE.
Так же как с неймспейсами, в системе определена цифровая нумерация индексов.

Все индексы прописываются в конфиге. Конфиг более менее человеко воспринимаем. Ниже в примерах будет использоваться следующий конфиг:
namespace[0].enabled = 1
namespace[0].index[0].type = "HASH"
namespace[0].index[0].unique = 1
namespace[0].index[0].key_field[0].fieldno = 0
namespace[0].index[0].key_field[0].type = "NUM"
 
namespace[0].index[1].type = "TREE"
namespace[0].index[1].unique = 0
namespace[0].index[1].key_field[0].fieldno = 1
namespace[0].index[1].key_field[0].type = "STR"
 
namespace[0].index[2].type = "TREE"
namespace[0].index[2].unique = 0
namespace[0].index[2].key_field[0].fieldno = 1
namespace[0].index[2].key_field[0].type = "STR"
namespace[0].index[2].key_field[1].fieldno = 2
namespace[0].index[2].key_field[1].type = "STR"
 
namespace[0].index[3].type = "HASH"
namespace[0].index[3].unique = 0
namespace[0].index[3].key_field[0].fieldno = 3
namespace[0].index[3].key_field[0].type = "NUM"
 

Пояснение:
используется один неймспейс, namespace=0
Первый индекс=0, является всегда первичным. Тип индекса HASH, наложен на числовое поле=0.
Второй индекс=1, тип TREE, накладывается на поле=1, тип строка.
Третий индекс =2, составной, накладывается на поля 1 и 2
Четвертый индекс=3 — накладывается на числовое поле 3

Инсталляция


1) качаем исходники:
** git clone git@github.com:akalend/tarantool.git
возможен переход в master  https://github.com/mailru/tarantool.git

2) cd connector/php

3) phpize

4) ./configure

5) sudo make install

6) в php.ini в секции extension вставляем строку:
extension=tarantool.so

Конструктор

// constructor(host,port);
$tnt = new Tarantool($host,$port);
 

Конструктор задает параметры соединения, Но само соединение происходит при первом обращении к данным.
Параметры $host, $port необязательные. Но умолчанию $host=127.0.0.1, $port =33013. Также в Tarantool имеется вторичный порт 33014, настроен только на чтение.

Вставка

Tarantool — оперирует порциями данных, именуемых кортежами.
В математике корте́ж — последовательность конечного числа элементов
В некоторых языках программирования (например Python или Lisp), кортеж — особый тип структуры данных
©Wikipedia
В РНР — корте́ж представлен как массив.
$tuple = array(1, 'x','abd', 1023 );
$res = $tnt->insert(0,$tuple);
var_dump($res);

Нулевой элемент массива вставится в нулевое поле данных.
Количество элементов массива может быть больше, чем кол-во индексных полей, Но в этом случае, выборка по этим полям будет невозможна. Если элемент уже существует, то он заменится на новый.
Результат true/false — результат выполнения операции INSERT

Выборка

выборка, аналогично интерфейсам РСУБД, осуществляется в два этапа: 1) оператор  выбора рекордсета SELECT и 2) итерирование по выборки строк, в нашем случае кортежей/tuple
ниже пример:
/**
 *  Tarantool::select
 * 
 *  @param number namespace
 *  @param number index No 
 *  @param mixed key 
 *  @param optional limit default all
 *  @param optional offset default 0
 * 
 *  @return count of tuples
 */

$count = $tnt->select(0,0,1); // namespace,index, key
var_dump($count);
$res = $tnt->getTuple();
var_dump($res);

Приведенный пример выбирает данные из namespace=0, index=0, key=1. Результат метода Select — кол-во выбранных кортежей. Выборка производится по первичному ключу. В данном случае — будет выбран один кортеж методом getTuple()

Если мы должны выбрать несколько элементов данных, то необходимо организовать цикл:
echo "some tuple select by fielNo[1] = 'x'\n";
$count = $tnt->select(0,1,'x'); // namespace,index, key
 
while( ($res = $tnt->getTuple()) != false){
    var_dump($res);
}

Если нужно выбрать по двум критериям, например аналог SQL оператора: SELECT * FROM t WHERE f1='msk' AND f2='realty', то необходимо использовать составной индекс. В нашем примере — это index=2. Смотрим конфиг.
echo "some tuple select by index = 2  (fielNo[1] = 'spb' and fielNo[2] = 'realry')\n";
$count = $tnt->select(0,2,array('spb', 'realty')); // namespace,index, key
while( ($res = $tnt->getTuple()) != false){
    var_dump($res);
}
 

Пример выборки по числовому полю(индекс=3)
echo "some tuple select by index = 3  (fielNo[3] = 1025)\n";
$res = $tnt->select(0,3,1025); // namespace,index, key
var_dump($res);
 
while( ($res = $tnt->getTuple()) != false){
    var_dump($res);
}
 

Если нужно организовать выборку частями, то предусмотрены параметры LIMIT/OFFSET (аналочигные в MySQL). Ниже пример выборки 5-ти кортежей, начиная с 10-го в рекордсете.
echo "some tuple select by index = 3  (fielNo[3] = 1025) NEXT 5 (offset=10, limit=5)\n";
$tnt->select(0,3,1025,5,10); // namespace,index, key, limit, offset
while( ($res = $tnt->getTuple()) != false){
    var_dump($res);
}


Изменение данных

В настоящий момент реализовано только два метода изменения данных: inc — увеличение данных, update — замена данных. Оба метода работают только по первичому индексу, т.е в качестве ключа используется только первичный индекс.

Рассмотрим более простой метод inc(). Данный метод увеличивает (по умолчанию на 1) поле типа NUM. На других типах полей возникнут ошибки.
/**
 *  Tarantool::inc
 * 
 *  @param namespace
 *  @param primary key
 *  @param field No for increment
 *  @param optional incremental data default +1
 * 
 *  @return bool    result
 */

// increment
$tnt->inc(0,1,3);
 
$tnt->select(0,0,1);
$tuple = $tnt->getTuple();
var_dump($tuple);
 
Если хотим уменьшить на 1, то используем:
$tnt->inc(0,1,3,-1);


Метод UPDATE отличается от INSERT тем, что UPDATE изменяет только необходимые нам поля данных, не трогая остальные. Метод INSERT — осуществляет, при наличие уже имеющихся данных первичного индекса все поля кортежа. Ближе к телупрактике:
/**
 *  Tarantool::update
 * 
 *  @param namespace
 *  @param primary key
 *  @param array of new data:
 *          array( fieldNo => newValue, ... )
 * 
 *  @return bool result
 */

$res = $tnt->update(0,1,array(2=>'y'));
echo "update tuple res=$res\n";
 
Второй параметр — это ключ выбора, третий параметр — это ассоциативный массив данных, которые необходимо заменить. Ключами массива являются числовые индексы, соответствующие номерам полей, которые необходимо заменить, на данные, которые соответствуют данным ключам.
Ограничения

пока реализовано только использование int32 индексов. int64 не реализовано.
не реализованы операции UPDATE/AND UPDATE/XOR

Надеюсь, что данный модуль будет полезен не только моему проекту. О замеченных багах прошу отписываться в личку, либо на страницу проекта.
Теги:
Хабы:
Всего голосов 30: ↑27 и ↓3+24
Комментарии32

Публикации

Истории

Ближайшие события