Switch lang: Русский \ English

A_Storage - DT Structure

DT

DT - Distributed Tree (Распределенное дерево) предназачена для хранения больших последовательностей в кластере

Основные преимущества структуры

  • + В ключах есть порядок. Можно итерировать ключи и запрашивать range
  • + данных можно поместить в DT очень много - гораздо больше чем "влезет" на любой сервер кластера - вся последовательность хранится "в целом на кластере" - распределенно
  • + при чтении данных из Глобального индекса , производительность высокая, как у KV

Недостатки :

  • - Небольшая скорость работы (30-60 insert/sec/tree/client , R,W вставленной записи — как в KV (3 реплики, 2 — кворум) для одного DT Tree : все клиенты сталкиваются и rps не превышает 100 rps для этого tree (3 реплики, 2 — кворум) )

Подходит для индексирования (reverse index) большого объёма данных , например wikipedia , который редко изменяется, но часто происходит обращение к индексу на чтение и поиск.

Два режима. Работа со структурой возможна в двух режимах :

  • Обычный
    • - нет транзакций
    • + скорость выше в 10 раз (на уровне касандры в обычном ее режиме)
  • Транзакционный
    • - медленнее (скорость в 10 раз медленнее кассандры)
    • + надежное изменение набора данных
    • + сохранение консистентности набора данных

Операции

Основные операции

    # чтение значения из ключа 
    await session.tree(random_tree()).get_cursor(random_key())

    # запись значения , вставка 
    await session.tree(random_tree()).cursor(random_key()).set(random_value())

    # получить вставленное значение 
    tree = session.tree(random_tree())
    key = random_key()
    value = random_value()
    await tree.cursor(key).set(value)
    value1 = (await tree.get_cursor(key)).value
    # assert  value1==value

навигация по дереву

        # делаем "случайное" дерево
        tree = session.tree(random_tree())
        await tree.cursor(['A', 'A']).set('foo')
        await tree.cursor(['A', 'B']).set('bar')
        await tree.cursor(['B', 'A']).set('baz')
        # читаем ключ, позицию запоминаем
        c = await tree.get_cursor(['A', 'A'])

        # NEXT 
        c = await c.next()
        assert c.key == ['A', 'B']
        assert c.value == 'bar'

        # NEXT again
        c = await c.next()
        assert c.key == ['B', 'A']
        assert c.value == 'baz'

        # NEXT again
        c = await c.next()
        assert c is None

Аналогично с prev

        tree = session.tree(random_tree())
        await tree.cursor(['A', 'A']).set('foo')
        await tree.cursor(['A', 'B']).set('bar')
        await tree.cursor(['B', 'A']).set('baz')

        c = await tree.get_cursor(['B', 'A'])

        c = await c.prev()
        assert c.key == ['A', 'B']
        assert c.value == 'bar'

        c = await c.prev()
        assert c.key == ['A', 'A']
        assert c.value == 'foo'

        c = await c.prev()
        assert c is None
Примеры с транзакциями

в транзакции из Python клиента работать очень просто

        # create tree object 
        tree = session.tree(random_tree())

        # начинаем транзакцию и в ней работаем , как обычно 
        async with session.transaction() as tx:
            # запись , вставка 
            await tree.cursor(['A'], tx).set('foo')
            await tree.cursor(['B'], tx).set('bar')

        async with session.transaction() as tx:
            # чтение 
            assert (await tree.get_cursor(['A'], tx)).value == 'foo'
            assert (await tree.get_cursor(['B'], tx)).value == 'bar'

транзакции добавляют свою логику. Например, если откатить транзакцию :

        tree = session.tree(random_tree())

        async with session.transaction() as tx:
            await tree.cursor(['A'], tx).set('foo')
            await tree.cursor(['B'], tx).set('bar')
            await tx.rollback()

        async with session.transaction() as tx:
            # данные остались старые = никакие
            assert (await tree.get_cursor(['A'], tx)).value is None
            assert (await tree.get_cursor(['B'], tx)).value is None

Range

Можно запросить диапазон ключей.

Это сложный функционал с точки зрения транзакционности и гарантий...

все параметры range описаны в документации

цитата оттуда :

    Возвращает отсортированный список ключей в дереве в указанный пределах.
    :param first: начальный ключ, не включается в ответ; по умолчанию - с первого
    :param last: последий ключ, включается в ответ; по умолчанию - до последнего включительно
    :param limit: максимальное количество ключей в ответе, начиная с первого; по умолчанию - нет ограничений
    :param transaction: если указан, запрос выполняется в транзакции
    :return: список объектов Cursor с данными
        tree = session.tree(random_tree())

        await tree.cursor(['A', 'A']).set('foo')
        await tree.cursor(['A', 'B']).set('bar')
        await tree.cursor(['B', 'A']).set('baz')

        # параметры по умолчанию. 

        result = await tree.range()
        assert len(result) == 3
        assert result[0].key == ['A', 'A']
        assert result[0].value == 'foo'
        assert result[1].key == ['A', 'B']
        assert result[1].value == 'bar'
        assert result[2].key == ['B', 'A']
        assert result[2].value == 'baz'

Указание начальной позиции :

        tree = session.tree(random_tree())

        await tree.cursor(['A', 'A']).set('foo')
        await tree.cursor(['A', 'B']).set('bar')
        await tree.cursor(['B', 'A']).set('baz')

        result = await tree.range(first=['A', 'A'])
        assert len(result) == 2
        assert result[0].key == ['A', 'B']
        assert result[0].value == 'bar'
        assert result[1].key == ['B', 'A']
        assert result[1].value == 'baz'

Указание заключительных позиций :

        tree = session.tree(random_tree())

        await tree.cursor(['A', 'A']).set('foo')
        await tree.cursor(['A', 'B']).set('bar')
        await tree.cursor(['B', 'A']).set('baz')

        result = await tree.range(last=['A', 'B'])
        assert len(result) == 2
        assert result[0].key == ['A', 'A']
        assert result[0].value == 'foo'
        assert result[1].key == ['A', 'B']
        assert result[1].value == 'bar'

Указание предельного размера выборки :

        tree = session.tree(random_tree())

        await tree.cursor(['A', 'A']).set('foo')
        await tree.cursor(['A', 'B']).set('bar')
        await tree.cursor(['B', 'A']).set('baz')

        result = await tree.range(limit=2)
        assert len(result) == 2
        assert result[0].key == ['A', 'A']
        assert result[0].value == 'foo'
        assert result[1].key == ['A', 'B']
        assert result[1].value == 'bar'

Аналогично работает и http api

Комментарии

Comments powered by Disqus
Перейти к главному содержимому