Close

15.01.2016

Как в Cassandra стыковать CQL и Thrift

Или на пути к своему CQL!!!

Из питона для cassandra есть два типа доступа: CQL и Thrift.

Можно работать из обоих одновременно.

Но есть особенности, вот о них мини пост.

API высокого уровня https://datastax.github.io/python-driver/getting_started.html

API низкого уровня http://pycassa.github.io/pycassa/index.html

Если посмотреть, как cassandra хранит данные, то станет понятно, что таблицы в CQL, это ColumnFamily в Thrift.

Но интроспекцией через pycassa таблицы CQL не видны.

kss = sys.list_keyspaces()
for ks in kss: 
	print('keyspace=',ks, ' column_fam_s=',sys.get_keyspace_column_families(ks, use_dict_for_col_metadata=False))

...
('keyspace=', 'mp_test', ' column_fam_s=', {})

И работать с ними никак — не находит!

Стал искать и гуглить, и оказалось что есть такие же горемыки и есть ответ.

Оказалось, что надо таблицы объявлять с with compact storage
я так попробовал (и НЕТ РЕЗУЛЬТАТА)

CREATE TABLE employees (
  company text,
  name text,
  age int,
  role text,
  PRIMARY KEY (company,name)
)with compact storage;

отвечает мне pycassa

Traceback (most recent call last):
  File "test1.py", line 30, in 
    )with compact storage;"""   )
  File "cassandra/cluster.py", line 1569, in cassandra.cluster.Session.execute (cassandra/cluster.c:26930)
  File "cassandra/cluster.py", line 3122, in cassandra.cluster.ResponseFuture.result (cassandra/cluster.c:59993)
cassandra.InvalidRequest: code=2200 [Invalid query] message="COMPACT STORAGE with composite PRIMARY KEY allows no more than one column not part of the PRIMARY KEY (got: age, role)"

типа у меня два столбца свободных осталось., ну я тогда один внёс в кластерный ключ, оставил свободным только один:

CREATE TABLE employees (
  company text,
  name text,
  age int,
  role text,
  PRIMARY KEY (company,name, age)
)with compact storage;

и далее:

import pycassa
from pycassa.pool import ConnectionPool
from pycassa.columnfamily import ColumnFamily
pool = ConnectionPool('mp_test', ['connectivity-s1.northeurope.cloudapp.azure.com:9160'])
col_fam = ColumnFamily(pool, 'employees')
result = col_fam.get('OSC')

дал ПРАВИЛЬНЫЙ результат

OSC => OrderedDict([((u'eric', 38), u'ceo')])
OrderedDict([((u'eric', 38), u'ceo')])

а интроспекция тоже правильный…

from pycassa.system_manager import *
sys = SystemManager('connectivity-s1.northeurope.cloudapp.azure.com:9160')
kss = sys.list_keyspaces()
for ks in kss: 
	print('keyspace=',ks, ' column_fam_s=',sys.get_keyspace_column_families(ks, use_dict_for_col_metadata=False))

в числе прочего напечатела:

('keyspace=', 'mp_test', ' column_fam_s=', {'employees': CfDef(comment='', key_validation_class='org.apache.cassandra.db.marshal.UTF8Type', min_compaction_threshold=4, key_cache_save_period_in_seconds=None, gc_grace_seconds=864000, default_validation_class='org.apache.cassandra.db.marshal.UTF8Type', max_compaction_threshold=32, read_repair_chance=0.0, compression_options={'chunk_length_kb': '64', 'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}, bloom_filter_fp_chance=0.01, id=None, keyspace='mp_test', key_cache_size=None, populate_io_cache_on_flush=None, replicate_on_write=None, subcomparator_type=None, merge_shards_chance=None, row_cache_provider=None, row_cache_save_period_in_seconds=None, column_type='Standard', memtable_throughput_in_mb=None, memtable_flush_after_mins=None, column_metadata=[], key_alias='company', dclocal_read_repair_chance=0.1, name='employees', compaction_strategy_options={'min_threshold': '4', 'max_threshold': '32'}, row_cache_keys_to_save=None, compaction_strategy='org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy', memtable_operations_in_millions=None, caching='KEYS_ONLY', comparator_type='org.apache.cassandra.db.marshal.CompositeType(org.apache.cassandra.db.marshal.UTF8Type,org.apache.cassandra.db.marshal.Int32Type)', row_cache_size=None)})

НУ как то так.

но я так и не знаю «почему только один свободный столбец?, как нам с этим быть ? нам то надо схемы более гибко задавать «,  и, думаю, что это плохо.

Я бы в таком случае написал бы просто свой CQL который может вообще всё. Напрашивается. Даже с джойнами и прочими прелестями, тем более нет проблемы-то.

 

2 Comments on “Как в Cassandra стыковать CQL и Thrift

Роман
16.01.2016 в 00:04

Thrift-API к кассандре уже давно deprecated, зачем его вообще использовать? А джойны — это путь SQL, а не путь Cassandra. В кассандре (и вообще в подобных БД) структуры данных размуно делить на две группы: на структуры, оптимизированные для записи и структуры, опитимизированные для чтения. Отдельно должен быть обработчик, берущий первые данные, модифицирующий, обрабатывающий, и создающий вторые. Если задача не очень хорошо ложиться на схему «читатели-писатели», то это хороший повод задуматься, а нужна ли кассандра тут вообще.

Ответить
Михаил Павлов
22.01.2016 в 20:14

Наша задча ложиться НЕ хорошо на неё, но выбор всё равно пал на касандру.
Дело в том, что у нас писать надо много и непрерывно. надо масштабировать её.
будет анализ и запросы чтения, разнообрази не велико, но частота средняя — меньше чем на запись.
Будет также много массированного чтения, когда зпускается анализ. предварительно укассандрымы расширим числореальных машин в кластере, чтобы поднять ops.

RDBMS нам не подходит т.к. у нас очень большие объёмы — он попросту плохо там кластеризуется.
Riak (Dinamo) и Couch не подошли.
Riak не имеет адекватного дискового бекенда, кроме BitCask, но он требует, чтобы ВСЕ ключи ноды помещались в памяти, а у нас не влезет.
Couch имеет только append-only storage, а у нас есть много данных, которые всё время изменяются.

Мы разрабатываем своё BigData решение (DT), но оно для совсем больших объёмов, а у нас сейчас меньше петабайта и после 400 ТБ рост закончится.

Про Mongo
Mongo хорошо подходит для динамических запросов. Или если вы хотите определять индексы, а не mapreduce функции. Если нужна большая производительность на большой базе.
Монго хорош если нравится CouchDB, но наши данные часто меняются, заполняя диски, вроде как бы и можно…
Например, для большинства вещей, для которых мы бы могли использовать MySQL или PostgreSQL, но заданная жёсткая структура данных только мешает.
Хранилище Mongo не очень нам подходит
Это движок основанный на отображаемых в память файлах. Он использует отображаемые в память файлы для ВСЕХ дисковых операций. И уже возможностями ОС управляется сбрасывание данных на диск и чтение страниц с и в память (как в LMDB). https://docs.mongodb.org/manual/faq/storage/
Это при не достаточной скорости дисков может привести к остановке работы БД. Чем то это напоминает in-memory стиль, хотя бы частично.
Главная причина почему не монго это отказоустойчивость.

Узлы Cassandra одинаковы (равного ранга, локальный лидер выбирается для задачи и то временно) и не имеют брокера или мастера.
Узлы MongoDB предоставляют жёсткую консистентность. Консистентность чтения «в конечном итоге» может быть получена через secondaries. MongoDB Cluster (с авто-шардингом и репликацией) имеет мастера в определённой точке во времени для каждого ведомого. http://blog.mongodb.org/post/475279604/on-distributed-consistency-part-1
Ещё одна причина (для нас не вполне существенная) это DBLocks при конкурентном доступе.
https://jira.mongodb.org/browse/SERVER-4328
https://docs.mongodb.org/manual/administration/monitoring/#locks
https://docs.mongodb.org/manual/faq/concurrency/

да еще и master — slaves, попытка держать консистентность, а нам бы лучше доступность в конечном счетё… , короче, ну его нахрен, этот Mongo!

надёжность и доступность для нас стала решающей, хотя ложиться на неё задача не очень-то.

Ответить

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

Ваш e-mail не будет опубликован. Обязательные поля помечены *