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
http://www.aerospike.com/download/ — на Windows
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> 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
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));