Александр Календарёв
Шаблоны структур данных NoSQL на примере Tarantool
План
Коротко паттернах
Структуры данных в Tarantool
РНР Интерфейс
Реализация Паттернов данных
Масштабирование
Виды паттернов
Системной архитектуры
Кодирования
Структур данных (РСУБД)
Паттерны данных NoSQL
Структура данных Tarantool
Namespace 0
Field 0 Field 1 Field 2
INDEX
1
INDEX
0
INDEX
2 . . .Field N
Tuple
Структура данных Tarantool
Namespace (Пространство имен)
Tuple (Кортеж)
Field (Поле)
Index (Индекс)
Аналог структур данных
Namespace - Таблица РСУБД
Field – Колонка (столбец) РСУБД
Структура данных Tarantool Типы полей
Num
Num64
String
Структура данных Tarantool Типы индексов
Hash / Tree
Простой / Составной
Операции в Tarantool
INSERT
SELECT
UPDATE
DELETE
PHP интерфейс ‐ Конструктор Tarantool
$tnt = new Tarantool($host,$port,$admPort);
$host – хост (def: localhost);
$port – порт (def: 33013);
$admPort – административный порт (33015).
PHP интерфейс ‐ INSERT Tarantool
define( ‘NS’,0); // номер namespace
$tnt = new Tarantool();
$tuple = array(12345,‘spb’,’Hello Word’);
$res = $tnt->insert(NS, $tuple);
Если данные существуют – они замещаются
Возвращается результат true- успех / false...
PHP интерфейс ‐ DELETE Tarantool
$tnt = new Tarantool();
$res = $tnt->delete(NS, $key, [$flag]);
1)Удаление всегда по первичному ключу
2) $flag = true – возвращать данные (def: $flag = false)
Возвращает: true/false – результат операции
или данные (массив) если $flag = true
PHP интерфейс ‐ UPDATE Tarantool
$tnt = new Tarantool();
$data = array(1=>’msk’, 2=> ‘Hello Hi++!’);
$res = $tnt->update(NS, $key, $data);
1)$key – всегда первичный ключ
2) $data – асс. массив № поля => нов. значение
Возвращает результат операции : true=успех/false...
PHP интерфейс ‐ INC (update) Tarantool
$tnt = new Tarantool();
$res = $tnt->inc(NS, $key, $fieldNo, [$delta, $flag]);
1)$key – всегда первичный ключ;
2) $fieldNo – номер инкременитируемого поля тип Num;
3) $delta – инкрементируемое значение (def: $delta = 1);
4) $flag = true – возвращать данные (def: $flag = false);
Возвращает результат операции : true=успех/false ...
или новые данные если $flag = true
PHP интерфейс ‐ SELECT Tarantool
$tnt = new Tarantool();
$count = $tnt->select(NS, $indexNo, $key,[ $limit, $offset]);
1)$key – ключ, если используем составной то массив;
2) $indexNo – номер индексного поля, по которому осуществляется выборка;
3) def: $limit = хFFFFFFFF; ,def: $offset = 0;
Возвращает: кол-во найденных кортежей,
Выборка данных осуществляется методом getTuple();
PHP интерфейс ‐ MSELECT Tarantool множественный выбор
Является аналогом mget($keys) в memcache
или: SELECT * FROM t0 WHERE key IN ($keyList);
$count = $tnt->mselect(NS, $indexNo, $keys,[ $limit, $offset]);
1)$keys –массив ключей;
2) $indexNo – номер индексного поля, осуществляется выборка;
3) $limi , $offset – аналог метода select();
Возвращает: кол-во найденных кортежей, false- ошибка
Выборка данных осуществляется методом getTuple();
PHP интерфейс – прочие методы Tarantool
getTuple() – возвращает данные методов
select() и mselect();
getError() – описание ошибки последней операции
getConf() – конфигурационный файл сервера
getInfo() – переменные сервера
getStat() – информация по статистики сервера
Паттерн: справочник
Field 0 , Primary index (PK)=0 Field1 = Name
11-22-33-44 Маня
11-22-33-55 Ваня
11-22-33-66 Таня
Аналог key/value Доступ осуществляется по первичному ключу; Возвращается один кортеж; SQL аналог:
SELECT * FROM T0 WHERE key0=$key
Паттерн: справочник реализация
define(‘PK’, 0);
$key = ’11-22-33-44’;
$res = $tnt->select(NS,PK, $key);
if($res===false)
echo $tnt->getError();
else
print_r( $tnt->getTuple());
Паттерн: обратный справочник
Field 0 , Primary index (PK)=0 Field1 = Name INDEX 1
11-22-33-44 Маня
11-22-33-55 Ваня
11-22-33-66 Таня
Доступ осуществляется по вторичному ключу; Возвращается массив кортежей;
SQL аналог:
SELECT * FROM T0 WHERE key1=$key
Паттерн: обратный справочник реализация define(‘IDX_NAME’, 1);
$key = ’Маня’;
$res = $tnt->select(NS, IDX_NAME, $key);
if($res===false)
echo $tnt->getError();
else
print_r( $tnt->getTuple());
Паттерн: справочник с разделами поиск по одному разделу
Field 0, Primary index INDEX=0 (PK)
Field1 = Name Field2 = City INDEX=2
11-22-33-44 Маня SPB
11-22-33-55 Ваня MSK
11-22-33-66 Таня SPB
Представляет денормолизованное отношение Один ко Многим Cтроится индекс по разделу Доступ осуществляется по вторичному ключу; SQL аналог: SELECT * FROM T0 WHERE key1=$key
Паттерн: справочник с разделами реализация define(‘IDX_CITY’, 2);
$key = ’SPB’;
$res = $tnt->select(NS, IDX_CITY, $key);
if($res===false)
echo $tnt->getError();
else
print_r( $tnt->getTuple());
Паттерн: справочник с разделами выборка по нескольким разделам
Field 0, Primary index (PK)=0
Field1 = Name Field2 = City (INDEX=3)
Field3=Sex INDEX=3
11-22-33-44 Маня SPB Ж
11-22-33-55 Ваня MSK M
11-22-33-66 Таня SPB Ж
11-22-33-77 Саня SPB M
Cтроится составной индекс по двум и более полям; Доступ осуществляется по вторичному ключу; SQL аналог:
SELECT * FROM T0 WHERE (Field2=$city AND Field3=$sex)
Паттерн: Матрица
Матрица [M x N]
Po = (x,y)
Key = y * M + x
Х
Y
M
N
Po
x
y
Паттерн: Матрица Задача: выбор области
Х
Y
M
р
N
Po
x
y
h
w
Паттерн: Матрица выбор области
$key = array();
for ($i=0; $i<W; $i++ )
for ($j=0; $j<H; $j++ )
$key[] = $P0 + I + j *M;
$tnt->mselect(NS, PK, $key);
Паттерн: Автоинкрементная таблица
Field 0 (PK) Field 1 = Phone Field2 = Name
1 11-22-33-44 Маня
2 11-22-33-55 Ваня
3 11-22-33-66 Таня
4 Новая строка
При каждой вставки увеличиваем PK на 1 Аналог Autoincrement в MySQL или SEQUENCE
Паттерн: Автоинкрементная таблица реализация
define(NS_USER, 1); // номер namespace USER
define(INC_USER,1); // номер ключа счетчика
define(FD_COUNTER,1); // номер поля счетчика
$key =
$tnt->inc(NS, INC_USER, FD_COUNTER,1,true);
$tnt->insert(NS_USER, $key, $data);
Паттерн: Отношение многие ко многим
Подход 1: создать Ns с двумя полями использовать составной индекс
Подход 2: использовать первичный индекс num64 Первая часть слова user_id, вторая часть map_id
Паттерн: Многие ко многим реализация варианта 2
define(NS_USER_TO_MAP, 3);
$key= $user_id << 32 + $map_id
$res=$tnt->select(NS_USER_TO_MAP, PK,$key);
Паттерн: Очередь
Принцип FIFO - Первый пришел, первый ушел
Реализуется через два указателя на начало и конец
очереди
PK
. . .
Data 1
Data 2
Data 3
Begin Pointer
End Pointer
Паттерн: Очередь добавление в очередь
define(BEG_PTR, 4); // номер ключа Beg Pointer
$key=
$tnt->inc(NS, BEG_PTR, FD_COUNTER,1,true);
$tnt->insert(NS_USER, $data);
Паттерн: Очередь взятие из очереди
define(END_PTR, 5); // номер ключа End Pointer
$key=
$tnt->inc(NS, END_PTR, FD_COUNTER,-1,true);
$data = $tnt->delete(NS_USER, $key, true);
Масштабирование
Принцип шардинга
0 ... 10М
10 ... 20М
20 ... 30М
0 ... 10М
10 ... 20М
20 ... 30М
Реализация шардинга Tarantool Proxy
0 ... 10М
10 ... 20М
20 ... 30М
Tarantool Proxy
Server 1
Server 2
Server 3
Application
Tarantool Proxy
Представляет многопоточный демон,
перенаправляющий запросы на Tarantool сервера.
Определение номера сервера:
• По конфигу или
• С помощью плагина
Tarantool Proxy: Операции с первичным ключом
• INSERT
• UPDATE
• DELETE
• SELECT * BY PK
Tarantool Proxy
Server 1
Server 2
Server 3
Tarantool Proxy: Операции со вторичным ключом
SELECT * FROM T1
WHERE k1=…
Tarantool Proxy
Server 1
Server 2
Server 3
Александр Календарёв
@akalend http://githab.com/akalend
http://akalend.habrahabr.ru/blog
Top Related