Как в 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 который может вообще всё. Напрашивается. Даже с джойнами и прочими прелестями, тем более нет проблемы-то.
Роман
16.01.2016 в 00:04Thrift-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!
надёжность и доступность для нас стала решающей, хотя ложиться на неё задача не очень-то.