Введение в key-value NoSQL БД Aerospike

Aerospike

Aerospike — это хранилище пар вида ключ-значение с моделью данных без использования схемы. Данные организованы в контейнеры с собственными политиками, называемыми «namespaces» (пространства имен), семантически близкими к понятию «databases» (базы данных) в реляционных БД. В переделах namespace, данные разделены на «sets» (наборы — схоже с таблицей в RDMS) и «records» (записи — схоже со строками в таблице). Каждая запись имеет индексный «key» который уникален в наборе, и один или более именованных «bins» (схоже с колонками), которые содержат значения, ассоциированные с record.

Концепция Aerospike в терминах MySQL

Aerospike MySQL
namespace db
set table
bin column
key primary key
record row
 Рассмотрим далее как установить и сконфигурировать Aerospike, а так же как использовать Java клиент.

Скачивание, установка и запуск Aerospike

http://www.aerospike.com/download/ — на Windows

На Linux
wget -O aerospike.tgz 'http://aerospike.com/download/server/latest/artifact/ubuntu12' | tar -xvf aerospike.tgz| sudo ./asinstall| sudo service aerospike start

Уникальный тип для Aerospike — Large Data Types (LDTs)

Что это такое эти LDTs? Уникальные для Aerospike, Large Data Types позволяют отдельным бинам одной записи (record Bins) (столбцам) содержать коллекции сотен тысяч объектов (или документов), и эти типы данных позволяют эффективно хранить эти коллекции и обрабатывать в БД. Данная особенность Aerospike — LDT использует механизм Aerospike User-Defined Functions и новый тип контейнера записей, который указан как «sub-records» (подзаписи).

Sub-records (подзаписи) очень похожи на обычные Aerospike records (записи),с главным отличием, что они связаны с родительской записью. Они делят одно и то же адресное пространство и внутреннюю  блокировку, как и родительская запись, так что они переносятся вместе с родительской записью во время миграций и они защищены одним и тем же механизмом изоляции.

Большие объекты в Aerospike не хранятся рядом с ассоциированной записью, вместо этого они делятся на подзаписи (sub-records — с размерами между 2kb и 32kb), как показано на рисунке. Подзаписи индексированы, связаны вместе, и обслуживаются внутри БД через User Defined Functions (UDFs).

 

Конфигурирование Aerospike

http://www.aerospike.com/docs/operations/configure/

# Конфигурационный файл Aerospike



service {
user root
group root
paxos-single-replica-limit 1 # Количество нод при котором количество реплик автоматически уменьшится до единицы
pidfile /var/run/aerospike/asd.pid
service-threads 4
transaction-queues 4
transaction-threads-per-queue 4
proto-fd-max 15000
}

logging {
# Log file must be an absolute path.
file /var/log/aerospike/aerospike.log {
context any info
}
}

network {
service {
address any #
port 3000
}

heartbeat {
mode multicast # Может быть или |multicast| или |mesh|. Multicast поддерживает только UDP протокол для передачи даных о состоянии кластера, mesh работает по TCP
# address 239.1.99.222 # только для multicast
# port 9918 # только для multicast

# Для использования unicast-mesh режима, удалите три строчки сверху и посмотрите
# aerospike_mesh.conf.
mode mesh
address 265.312.999.555 # IP address
# mesh-port 3002
interval 150 # Интервал в милисекундах, через который посылаются данные о состоянии.
timeout 40 # Количество пропущенных heartbeats, после которого удаленная нода будет объявлена мертвой. (150ms x 40 = 6 seconds)

}

fabric {
port 3001
}

info {
port 3003
}
}

namespace akorsa {
replication-factor 2 # Количество копий записи (включаю мастер копию) содержащихся в целом кластере.
default-ttl 30d # Time-To-Live 30 дней, используйте 0 для бесконечного времени жизни.

enable-xdr false # Позволяет включить репликацию на уровне дата-центров see http://www.aerospike.com/docs/architecture/xdr.html
set-disable-eviction false # сервер будет удалять старые записи, если память или диск станет полным
high-water-memory-pct 60 # Данные будут удалены, если утилизация памяти достигнет более указанного процента
high-water-disk-pct 50 # Данные будут удалены, если утилизация диска достигнет более указанного процента</pre><pre>stop-writes-pct 90 # Запретить запись (кроме удалений) когда утилизация памяти выше указанного процента.
} 
namespace test { 
replication-factor 2 
memory-size 4G 
default-ttl 30d 
storage-engine memory 
load-at-startup true # on startup load data from storage and not start with empty db 
data-in-memory true # хранить данные в памяти, иначе только индекс будет храниться в памяти. Рекомендуется использовать если диск не SSD 
} 
namespace bar { 
replication-factor 2 
memory-size 4G 
default-ttl 30d 
storage-engine device { 
file /opt/aerospike/data/bar.dat 
filesize 16G 
data-in-memory true # Хранить данные в памяти в добавок к файлу
} 
} 

Размер записи (record)

Дефолтный максимальный размер record составляет  128 KB

 com.aerospike.client.AerospikeException: Error Code 13: Record too big

Можно увеличить следующим способом:

namespace mynamespace {
storage-engine device {
write-block-size 1M # Max size in bytes for each record (LDT entries might be larger)
}
}

Максимум это 1MB

attempted to configure write block size in excess of 1048576 

Клиент AQL Client

aql это SQL подобный клиент для aerospike

aql Management

Базы данных

 aql> show namespaces 

Таблицы

aql> show sets

Столбцы

 aql> show bins
+-------+-------------+-------+-----------+
| quota | bin | count | namespace |
+-------+-------------+-------+-----------+
| 32768 | "firstname" | 3 | "test" |
| 32768 | "height" | 3 | "test" |
| 32768 | "id" | 3 | "test" |
+-------+-------------+-------+-----------+

Query


aql> select * from test.people

aql> select firstname, height, id from test.people

Для фильтрации нужен индекс


aql> select firstname, height, id from test.people where id=42
0 rows in set (0.001 secs)
Error: (201) AEROSPIKE_ERR_INDEX_NOT_FOUND

aql> CREATE INDEX user_age_idx ON test.people (height) NUMERIC

aql> select firstname, height, id from test.people where height=187
aql> select firstname, height, id from test.people where height between 187 and 190

Получить запись через первичный ключ:


select * from mynamespace.myset where PK='foo'

http://www.aerospike.com/docs/guide/query.html

http://www.aerospike.com/docs/guide/aggregation.html

Используем Java клиент

http://www.aerospike.com/docs/client/java/install/


import com.aerospike.client.AerospikeClient;
import com.aerospike.client.Bin;
import com.aerospike.client.Host;
import com.aerospike.client.Key;
import com.aerospike.client.Record;
import com.aerospike.client.policy.ClientPolicy;

...

Host[] hosts = new Host[] {
new Host("127.0.0.1", 3000),
};

try(AerospikeClient client = new AerospikeClient(new ClientPolicy(), hosts)) {

// this namespace needs to exist in the aerospike configuration
String namespaceName="test";
String setName="people";
String bin1Name="firstname";
String bin2Name="height";
String bin3Name="id";

Integer id=1;
Key key = new Key(namespaceName, setName, id);
Bin bin1 = new Bin(bin1Name, "John");
Bin bin2 = new Bin(bin2Name, 182);
Bin bin3 = new Bin(bin3Name, id);

// Write a record
client.put(null, key, bin1, bin2, bin3);

// Read a record
Record record = client.get(null, key);
System.err.println(record); // (gen:4),(exp:182531601),(bins:(firstname:John),(id:1),(height:182))
String fstName=record.getString(bin1Name);
System.err.println(fstName); // John
}

Размещаем списки или maps в бин и читаем и записываем их через AeroSpike

https://github.com/aerospike/aerospike-client-java/blob/master/examples/src/com/aerospike/examples/LargeMap.java

 Для использования LDT необходимо подключить опцию в необходимом namespace

namespace mynamespace {
ldt-enabled true # large data types, require to put lists and maps as values into bins
}


final LargeMap lmap = client.getLargeMap(writePolicy, new Key(namespace, trackingId, recordKey), "myBin", null);
final Map<?, ?> filteredValues = lmap.get(Value.get(fieldKey));
final Object result = filteredValues.get(fieldKey);

И записываем в него:


final LargeMap lmap = client.getLargeMap(writePolicy, new Key(namespace, trackingId, recordKey), "myBin", null);
lmap.put(Value.get(fieldKey), Value.get(yourValue));

Удаляем


final LargeMap lmap = client.getLargeMap(writePolicy, new Key(namespace, trackingId, recordKey), "myBin", null);
lmap.remove(Value.get(field));

(Visited 876 times, 1 visits today)

Добавить комментарий

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.