Вступление
В прошлый раз я писал о Hadoop на Heroku, который является надстройкой от Treasure Data — на этот раз я собираюсь рассказать о NoSQL на Heroku.
Существуют различные службы хранилища данных — дополнения в терминах Heroku — от MongoDB (MongoHQ) до CouchDB (Cloudant) и Cassandra (Cassandra.io). Этот пост посвящен Cassandra.io.
Cassandra.io
Cassandra.io — это управляемое и управляемое кольцо Cassandra, основанное на Apache Cassandra, которое делает его доступным через RESTful API. На момент написания этой статьи клиентские вспомогательные библиотеки Cassandra.io доступны на Java, Ruby и PHP, а также имеется версия Objective-C в закрытой бета-версии. Библиотеки можно скачать с github. Я использую библиотеку Java в своих тестах.
Heroku — и дополнение Cassandra.io — построено на Amazon Elastic Compute Cloud (EC2) и поддерживается во всех местоположениях Amazon. Примечание: надстройка Cassandra.io теперь находится в публичной бета-версии, что означает, что у вас есть только одна опция под названием Test — это бесплатно.
Установка дополнения Cassandra.io
Для установки дополнения Cassandra.io вам просто нужно следовать стандартному способу добавления дополнения в приложение:
$ heroku login Enter your Heroku credentials. Email: address@example.com Password (typing will be hidden): Authentication successful. $ heroku create Creating glacial-badlands-1234... done, stack is cedar http://glacial-badlands-1234.herokuapp.com/ | git@heroku.com:glacial-badlands-1234.git $ heroku addons:add cassandraio:test --app glacial-badlands-1234 Adding cassandraio:test on glacial-badlands-1234... done, v2 (free) Use `heroku addons:docs cassandraio:test` to view documentation.
Вы можете проверить конфигурацию через консоль администратора Heroku:
Затем вам нужно клонировать клиентские вспомогательные библиотеки из github:
$ git clone https://github.com/m2mIO/cassandraio-client-libraries.git
В случае клиентской библиотеки Java вам также понадобится библиотека gson Google (gson-2.0.jar).
Написание приложения Cassandra.io
Библиотека Java RESTful API имеет один простой файл конфигурации с именем sdk.properties. В нем хранится очень мало параметров — URL-адрес API и версия. Исходный файл sdk.properties, клонированный из github, имеет неправильную версию (v0.1), его необходимо изменить на 1. Вы можете проверить необходимые параметры конфигурации с помощью команды heroku config .
$ heroku config --app glacial-badlands-1234 === glacial-badlands-1234 Config Vars CASSANDRAIO_URL: https://Token:AccountId@api.cassandra.io/1/welcome
Вы можете проверить те же параметры конфигурации из консоли администратора Heroku, хотя URL вводит в заблуждение:
Файл sdk.properties должен выглядеть следующим образом:
apiUrl = https://api.cassandra.io version = 1
Код Java — CassandraIOTest.java — выглядит следующим образом:
package io.cassandra.tests;
import java.util.ArrayList;
import java.util.List;
import io.cassandra.sdk.StatusMessageModel;
import io.cassandra.sdk.column.ColumnAPI;
import io.cassandra.sdk.columnfamily.ColumnFamilyAPI;
import io.cassandra.sdk.constants.APIConstants;
import io.cassandra.sdk.data.DataAPI;
import io.cassandra.sdk.data.DataBulkModel;
import io.cassandra.sdk.data.DataColumn;
import io.cassandra.sdk.data.DataMapModel;
import io.cassandra.sdk.data.DataRowkey;
import io.cassandra.sdk.keyspace.KeyspaceAPI;
public class CassandraIOTest {
// credentials
private static String TOKEN = "<Token>";
private static String ACCOUNTID = "<AccountId>";
// data
private static String KS = "AAPL";
private static String CF = "MarketData";
private static String COL1 = "Open";
private static String COL2 = "Close";
private static String COL3 = "High";
private static String COL4 = "Low";
private static String COL5 = "Volume";
private static String COL6 = "AdjClose";
private static String RK = "18-05-2012";
public static void main(String[] args) {
try {
StatusMessageModel sm;
// Create Keyspace
KeyspaceAPI keyspaceAPI = new KeyspaceAPI(APIConstants.API_URL, TOKEN, ACCOUNTID);
sm = keyspaceAPI.createKeyspace(KS);
System.out.println(sm.getMessage() + " | " + sm.getDetail() + " | "
+ sm.getError());
// Create ColumnFamily
ColumnFamilyAPI columnFamilyAPI = new ColumnFamilyAPI(APIConstants.API_URL, TOKEN,
ACCOUNTID);
sm = columnFamilyAPI.createColumnFamily(KS, CF,
APIConstants.COMPARATOR_UTF8);
System.out.println(sm.getMessage() + " | " + sm.getDetail() + " | "
+ sm.getError());
// Add Columns (High, Low, Open, Close, Volume, AdjClose)
ColumnAPI columnAPI = new ColumnAPI(APIConstants.API_URL, TOKEN, ACCOUNTID);
sm = columnAPI.upsertColumn(KS, CF, COL1,
APIConstants.COMPARATOR_UTF8, true);
System.out.println(sm.getMessage() + " | " + sm.getDetail() + " | "
+ sm.getError());
sm = columnAPI.upsertColumn(KS, CF, COL2,
APIConstants.COMPARATOR_UTF8, true);
System.out.println(sm.getMessage() + " | " + sm.getDetail() + " | "
+ sm.getError());
sm = columnAPI.upsertColumn(KS, CF, COL3,
APIConstants.COMPARATOR_UTF8, true);
System.out.println(sm.getMessage() + " | " + sm.getDetail() + " | "
+ sm.getError());
sm = columnAPI.upsertColumn(KS, CF, COL4,
APIConstants.COMPARATOR_UTF8, true);
System.out.println(sm.getMessage() + " | " + sm.getDetail() + " | "
+ sm.getError());
sm = columnAPI.upsertColumn(KS, CF, COL5,
APIConstants.COMPARATOR_UTF8, true);
System.out.println(sm.getMessage() + " | " + sm.getDetail() + " | "
+ sm.getError());
sm = columnAPI.upsertColumn(KS, CF, COL6,
APIConstants.COMPARATOR_UTF8, true);
System.out.println(sm.getMessage() + " | " + sm.getDetail() + " | "
+ sm.getError());
//Add Bulk Data
DataAPI dataAPI = new DataAPI(APIConstants.API_URL, TOKEN, ACCOUNTID);
List columns = new ArrayList();
DataColumn dc = new DataColumn(COL1, "533.96");
columns.add(dc);
dc = new DataColumn(COL2, "530.38", 12000);
columns.add(dc);
dc = new DataColumn(COL3, "543.41", 12000);
columns.add(dc);
dc = new DataColumn(COL4, "522.18", 12000);
columns.add(dc);
dc = new DataColumn(COL5, "26125200", 12000);
columns.add(dc);
dc = new DataColumn(COL6, "530.12", 12000);
columns.add(dc);
List rows = new ArrayList();
DataRowkey row = new DataRowkey(RK, columns);
rows.add(row);
DataBulkModel dataBulk = new DataBulkModel(rows);
sm = dataAPI.postBulkData(KS, CF, dataBulk);
System.out.println(sm.getMessage() + " | " + sm.getDetail() + " | "
+ sm.getError());
// Get Data
DataMapModel dm = dataAPI.getData(KS, CF, RK, 0, null);
System.out.println(dm.toString());
// Delete Keyspace
sm = keyspaceAPI.deleteKeyspace(KS);
System.out.println(sm.getMessage() + " | " + sm.getDetail() + " | "
+ sm.getError());
}
catch(Exception e) {
System.out.println(e.getMessage());
}
}
}
Результат выполнения:
09-Sep-2012 22:59:18 io.cassandra.sdk.CassandraIoSDK constructAPIUrl
INFO: API URL: https://api.cassandra.io/1/keyspace/AAPL/
Success | Keyspace added successfully. | null
09-Sep-2012 22:59:21 io.cassandra.sdk.CassandraIoSDK constructAPIUrl
INFO: API URL: https://api.cassandra.io/1/columnfamily/AAPL/MarketData/UTF8Type/
Success | MarketData ColumnFamily created successfully | null
09-Sep-2012 22:59:24 io.cassandra.sdk.CassandraIoSDK constructAPIUrl
INFO: API URL: https://api.cassandra.io/1/column/AAPL/MarketData/Open/UTF8Type/?isIndex=true
Failed | Unable to create Column: Open | Cassandra encountered an internal error processing this request: TApplicationError type: 6 message:Internal error processing system_update_column_family
09-Sep-2012 22:59:24 io.cassandra.sdk.CassandraIoSDK constructAPIUrl
INFO: API URL: https://api.cassandra.io/1/column/AAPL/MarketData/Close/UTF8Type/?isIndex=true
Success | Close Column upserted successfully | null
09-Sep-2012 22:59:26 io.cassandra.sdk.CassandraIoSDK constructAPIUrl
INFO: API URL: https://api.cassandra.io/1/column/AAPL/MarketData/High/UTF8Type/?isIndex=true
Success | High Column upserted successfully | null
09-Sep-2012 22:59:27 io.cassandra.sdk.CassandraIoSDK constructAPIUrl
INFO: API URL: https://api.cassandra.io/1/column/AAPL/MarketData/Low/UTF8Type/?isIndex=true
Success | Low Column upserted successfully | null09-Sep-2012 22:59:29 io.cassandra.sdk.CassandraIoSDK constructAPIUrl
INFO: API URL: https://api.cassandra.io/1/column/AAPL/MarketData/Volume/UTF8Type/?isIndex=true
Success | Volume Column upserted successfully | null
09-Sep-2012 22:59:30 io.cassandra.sdk.CassandraIoSDK constructAPIUrl
INFO: API URL: https://api.cassandra.io/1/column/AAPL/MarketData/AdjClose/UTF8Type/?isIndex=true
Success | AdjClose Column upserted successfully | null
Posting JSON: {"rowkeys":[{"rowkey":"18-05-2012","columns":[{"columnname":"Open","columnvalue":"533.96","ttl":0},{"columnname":"Close","columnvalue":"530.38","ttl":12000},{"columnname":"High","columnvalue":"543.41","ttl":12000},{"columnname":"Low","columnvalue":"522.18","ttl":12000},{"columnname":"Volume","columnvalue":"26125200","ttl":12000},{"columnname":"AdjClose","columnvalue":"530.12","ttl":12000}]}]}
09-Sep-2012 22:59:32 io.cassandra.sdk.CassandraIoSDK constructAPIUrl
INFO: API URL: https://api.cassandra.io/1/data/AAPL/MarketData/
Success | Bulk upload successfull. | null
09-Sep-2012 22:59:32 io.cassandra.sdk.CassandraIoSDK constructAPIUrl
INFO: API URL: https://api.cassandra.io/1/data/AAPL/MarketData/18-05-2012/
{Volume=26125200, Open=533.96, Low=522.18, High=543.41, Close=530.38, AdjClose=530.12}
09-Sep-2012 22:59:32 io.cassandra.sdk.CassandraIoSDK constructAPIUrl
INFO: API URL: https://api.cassandra.io/1/keyspace/AAPL/
Success | Keyspace dropped successfully. | null
Анализ
Шаг 1. / Код создает пространство ключей с именем AAPL, используя HTTP POST, URL: https://api.cassandra.io/1/keyspace/AAPL/
Он использует класс KeySpaceAPI с Token и AccountId в качестве параметров для конструктора. Токен используется как имя пользователя, а AccountID — пароль. (Помните: эти атрибуты можно получить с помощью команды настройки heroku или через консоль администратора Heroku)
Шаг 2. / Затем код создает семейство столбцов с именем MarketData. Он использует ColumnFamilyAPI — с указанными выше учетными данными — и URL-адрес REST — https://api.cassandra.io/1/columnfamily/AAPL/MarketData/UTF8Type/.
Шаг 3. / Затем код вставляет кумны, называемые Open, Close, High, Low, Volume и AjdClose. Он использует ColumnAPI — те же учетные данные, которые мы уже знаем — и URL REST — https://api.cassandra.io/1/column/AAPL/MarketData/Open/UTF8Type/?isIndex=true, где AAPL — это пространство ключей, MarketData — это семейство столбцов и Open — столбец.
Шаг 4. / Затем код подготавливает данные в виде пар имя / значение (Open = «533.96 ″, Close =« 530.38 ″ и т. Д.), Определяет ключ строки («18-05-2012 ″) и использует метод DataAPI postBulkData для загрузить данные в Cassandra.io. Учетные данные DataAPI такие же, как указано выше.
Шаг 5. / Затем код извлекает данные, используя HTTP GET с URL: https://api.cassandra.io/1/data/AAPL/MarketData/18-05-2012/. Ответ в формате JSON: {Volume = 26125200, Open = 533,96, Low = 522,18, High = 543,41, Close = 530,38, AdjClose = 530.12}
Шаг 6. / Наконец код уничтожает пространство ключей, используя HTTP DELETE, URL: https://api.cassandra.io/1/keyspace/AAPL/.
Резюме
Если вы хотите опробовать надежный, высокодоступный хранилище данных Casssandra без каких-либо предварительных инвестиций в инфраструктуру и с простым в использовании API, вы, безусловно, можете ближе познакомиться с Cassandra.io на Heroku. Запуск занимает всего несколько минут, и API предлагают разработчикам Java, Ruby и PHP простое управление данными на основе REST.

