Статьи

Все, что вам нужно знать об архитектуре Couchbase


После того, как я получил много хороших отзывов и комментариев о
моем последнем блоге на MongoDb , мне было предложено сделать еще одно глубокое погружение в другой популярный db, ориентированный на документы; Couchbase.

Я давний поклонник CouchDb и
написал блог об этом много лет назад . После того, как он слился с Membase, я очень взволнован, чтобы еще раз глубоко в него взглянуть.

Couchbase — это слияние двух популярных технологий NOSQL: 

  • Membase, обеспечивающая постоянство, репликацию и передачу по высокопроизводительной технологии memcached
  • CouchDB, которая является пионером в документно-ориентированной модели на основе JSON

Как и другие технологии NOSQL, и Membase, и CouchDB изначально созданы на основе высокораспределенной архитектуры с разделением данных между компьютерами в кластере. Построенная на основе протокола Memcached, Membase обеспечивает простую миграцию для существующих пользователей Memcached, которые хотят добавить постоянство, сегментирование и отказоустойчивость к своей знакомой модели Memcached. С другой стороны, CouchDB обеспечивает первоклассную поддержку для хранения документов JSON, а также простой RESTful API для доступа к ним. Внизу CouchDB также имеет высоко настроенный механизм хранения, который оптимизирован как для транзакции обновления, так и для обработки запросов. Используя все преимущества обеих технологий, Membase хорошо позиционируется на рынке NOSQL.

Модель программирования

Couchbase предоставляет клиентские библиотеки для различных языков программирования, таких как Java / .NET / PHP / Ruby / C / Python / Node.js.

Для чтения Couchbase предоставляет механизм поиска на основе ключей, где клиент должен предоставлять ключ, и только с сервером, на котором размещены данные (с этим ключом) свяжутся.

Couchbase также предоставляет механизм запросов для извлечения данных, когда клиент предоставляет запрос (например, диапазон на основе некоторого вторичного ключа), а также представление (в основном, индекс). Запрос будет транслироваться на все серверы в кластере, а результат будет объединен и отправлен обратно клиенту.

Для записи Couchbase предоставляет механизм обновления на основе ключей, при котором клиент отправляет обновленный документ с ключом (как идентификатор документа). При обработке запроса на запись сервер вернется к клиентскому запросу на запись, как только данные будут сохранены в оперативной памяти на активном сервере, что обеспечивает минимальную задержку для запросов на запись.

Ниже приводится основной API, который предлагает Couchbase. (в абстрактном смысле)

# Get a document by key

doc = get(key)

# Modify a document, notice the whole document 
#   need to be passed in

set(key, doc)

# Modify a document when no one has modified it 
#  since my last read

casVersion = doc.getCas()
cas(key, casVersion, changedDoc)

# Create a new document, with an expiration time 
#   after which the document will be deleted

addIfNotExist(key, doc, timeToLive)

# Delete a document

delete(key)

# When the value is an integer, increment the integer

increment(key)

# When the value is an integer, decrement the integer

decrement(key)

# When the value is an opaque byte array, append more 
#  data into existing value 

append(key, newData)

# Query the data 

results = query(viewName, queryParameters)

In Couchbase, document is the unit of manipulation.  Currently Couchbase doesn’t support server-side execution of custom logic.  Couchbase server is basically a passive store and unlike other document oriented DB, Couchbase doesn’t support field-level modification.  In case of modifying documents, client need to retrieve documents by its key, do the modification locally and then send back the whole (modified) document back to the server.  This design tradeoff network bandwidth (since more data will be transferred across the network) for CPU (now CPU load shift to client).

Couchbase currently doesn’t support bulk modification based on a condition matching.  Modification happens only in a per document basis.  (client will save the modified document one at a time).

Transaction Model

Подобно многим базам данных NOSQL, модель транзакций Couchbase примитивна по сравнению с RDBMS. Атомарность гарантируется для одного документа, а транзакции, которые охватывают обновление нескольких документов, не поддерживаются. Чтобы обеспечить необходимую изоляцию для одновременного доступа, Couchbase предоставляет механизм CAS (сравнение и замена), который работает следующим образом:

  • Когда клиент получает документ, к нему прикрепляется идентификатор CAS (эквивалентный номеру ревизии).
  • Пока клиент манипулирует извлеченным документом локально, другой клиент может изменить этот документ. Когда это происходит, идентификатор CAS документа на сервере будет увеличиваться.
  • Теперь, когда исходный клиент отправляет свою модификацию на сервер, он может прикрепить исходный идентификатор CAS в своем запросе. Сервер проверит этот идентификатор с фактическим идентификатором на сервере. Если они различаются, документ был обновлен между ними, и сервер не будет применять обновление.
  • Исходный клиент повторно прочитает документ (который теперь имеет более новый идентификатор) и повторно отправит его модификацию. 

Couchbase также предоставляет механизм блокировки для клиентов, чтобы координировать их доступ к документам. Клиенты могут запросить блокировку для документа, который он намерен изменить, обновить документы и затем разблокировать блокировку. Чтобы предотвратить ситуацию взаимоблокировки, каждый грант LOCK имеет тайм-аут, поэтому он будет автоматически освобожден через определенный промежуток времени.

Архитектура развертывания

 Как правило, база данных Couchbase находится в кластерах серверов, включающих несколько компьютеров. Клиентская библиотека подключится к соответствующим серверам для доступа к данным. Каждая машина содержит несколько процессов-демонов, которые обеспечивают доступ к данным, а также функции управления.

Сервер данных, написанный на C / C ++, отвечает за обработку запроса get / set / delete от клиента. Сервер управления, написанный на Erlang, отвечает за обработку трафика запросов от клиента, а также за управление конфигурацией и обмен данными с другими узлами-членами кластера.

Виртуальные ведра

Основной единицей хранения данных в Couchbase DB является документ JSON (или примитивный тип данных, такой как int и байтовый массив), который связан с ключом. Все пространство ключей разделено на логическую единицу хранения 1024, называемую «виртуальные корзины» (или vBucket). vBucket распределяется по компьютерам в кластере с помощью карты, которая используется как серверами кластера, так и клиентской библиотекой.

Высокая доступность достигается за счет репликации данных на уровне vBucket. В настоящее время Couchbase поддерживает одну активную ноль или более резервных реплик vBucket, размещенных на других машинах. В настоящий момент резервный сервер простаивает и не обслуживает ни одного клиентского запроса. В будущей версии Couchbase резервная реплика сможет обслуживать запрос на чтение.

Балансировка нагрузки в Couchbase достигается следующим образом:

  • Keys are uniformly distributed based on the hash function
  • When machines are added and removed in the cluster.  The administrator can request a redistribution of vBucket so that data are evenly spread across physical machines.

Management Server

Сервер управления выполняет функцию управления и координирует другие узлы в кластере. Он включает в себя следующие функции мониторинга и администрирования

Heartbeat: сторожевой процесс периодически связывается со всеми узлами-участниками в одном кластере для предоставления обновлений работоспособности Couchbase Server.

Монитор процессов: эта подсистема контролирует выполнение локального менеджера данных, перезапуская сбойные процессы по мере необходимости и предоставляет информацию о состоянии модулю пульса.

Диспетчер конфигурации: каждый узел Couchbase Server имеет общую кластерную конфигурацию, которая содержит узлы-члены в кластере, карту vBucket. Менеджер конфигурации извлекает эту конфигурацию из других узлов-участников во время загрузки.

Внутри кластера сервер управления одного узла будет выбран в качестве лидера, который выполняет следующую функцию управления для всего кластера.

  • Управляет распределением vBuckets среди других узлов и инициирует миграцию vBucket
  • Управляет аварийным переключением и обновляет диспетчер конфигурации узлов-участников

В случае сбоя узла лидера новый лидер будет выбран из оставшихся в живых участников кластера.

Когда происходит сбой машины в кластере, лидер обнаруживает это и уведомляет участвующие машины в кластере, что все vBuckets, размещенные на разбитой машине, мертвы. После получения этого сигнала машины, на которых размещена соответствующая реплика vBucket, установят статус vBucket как «активный». Карта vBucket / server обновляется и в конечном итоге распространяется на клиентскую библиотеку. Обратите внимание, что в этот момент уровень репликации vBucket будет снижен. Couchbase не создает автоматически новые реплики, которые вызывают трафик копирования данных. Администратор может выполнить команду, чтобы явно инициировать перебалансировку данных. Аварийный компьютер, после перезагрузки может вернуться в кластер. В этот момент все ранее сохраненные данные будут полностью удалены, и машина будет рассматриваться как совершенно новая пустая машина.

По мере того, как все больше машин помещается в кластер (для масштабирования), vBucket следует перераспределить для достижения баланса нагрузки. Это в настоящее время вызвано явной командой от администратора. Как только получит команду «rebalance», лидер вычислит новую предварительную карту, которая имеет сбалансированное распределение vBuckets, и отправит эту предварительную карту всем членам кластера.

Чтобы вычислить карту vBucket и план миграции, лидер пытается решить следующие задачи:

  • Равномерно распределите количество активных vBuckets и реплики vBuckets между узлами-членами.
  • Поместите активную копию и каждую реплику в физически разделенные узлы.
  • Распространите реплику vBucket как можно шире среди других узлов-членов.
  • Минимизировать объем миграции данных
  • Orchestrate the steps of replica redistribution so no node or network will be overwhelmed by the replica migration.

После определения карт vBucket лидер передает карту перераспределения каждому участнику кластера и координирует шаги миграции vBucket. Фактическая передача данных происходит непосредственно между узлом отправления и узлом назначения.

Обратите внимание, что, поскольку у нас обычно больше vBuckets, чем машин. Рабочая нагрузка миграции будет равномерно распределена автоматически. Например, когда новые машины добавляются в кластеры, все существующие машины будут мигрировать некоторую часть своего vBucket на новые машины. В кластере нет ни одного узкого места.

Пропускная способность миграции и перераспределения vBucket между серверами, жизненный цикл vBucket на сервере будет в одном из следующих состояний

  • «Активный»: означает, что на сервере размещен vBucket, готовый обрабатывать запросы как на чтение, так и на запись.
  • «Реплика»: означает, что на сервере размещена копия vBucket, которая может быть немного устаревшей, но может принять запрос на чтение, который допускает некоторую степень устаревания.
  • «Ожидание»: означает, что на сервере размещена копия, которая находится в критическом переходном состоянии. В данный момент сервер не может принять запрос на чтение или запись.
  • «Мертвый»: означает, что сервер больше не отвечает за vBucket и больше не будет принимать запросы на чтение или запись.

Сервер данных

Сервер данных реализует API memcached, такие как get, set, delete, append, prepend и т. Д. Он содержит следующую ключевую структуру данных:

  • Одна хеш-таблица в памяти (ключ по идентификатору документа) для соответствующего хоста vBucket. Хэш-таблица действует как метаданные для всех документов, а также как кэш для содержимого документа. Ведение записи дает быстрый способ определить, существует ли документ на диске.
  • Для поддержки асинхронной записи в vBucket имеется связанный список контрольных точек, содержащий идентификатор документа измененных документов, которые не были записаны на диск или реплицированы на реплику.

Для обработки запроса «GET»

  • Сервер данных направляет запрос соответствующему ep-движку, ответственному за vBucket.
  • Ep-engine будет искать идентификатор документа из таблицы в памяти. Если содержимое документа найдено в кеше (сохранено в значении хеш-таблицы), оно будет возвращено. В противном случае будет создана фоновая задача извлечения диска и помещена в очередь диспетчера RO.
  • Затем диспетчер RO считывает значение из базового механизма хранения и заполняет соответствующую запись в хэш-таблице vbucket.
  • Наконец, поток уведомлений уведомляет о завершении извлечения диска для ожидающего подключения к memcached, так что рабочий поток memcached может повторно обработать механизм для обработки запроса get.

Для обработки запроса «SET» вызывающему клиенту будет возвращен успешный ответ, как только обновленный документ будет помещен в хеш-таблицу в памяти с запросом записи, помещенным в буфер контрольной точки. Позже поток Flusher будет получать ожидающий запрос записи из каждого буфера контрольных точек, искать соответствующий контент документа из хеш-таблицы и записывать его в механизм хранения.

Конечно, данные могут быть потеряны в случае сбоя сервера до того, как данные будут реплицированы на другой сервер и / или сохранены. Если клиенту требуется высокая доступность данных при различных сбоях, он может выполнить последующий вызов Наблюдения (), который блокирует условие, что сервер сохраняет данные на диске, или сервер реплицировал данные на другой сервер (и получает ACK) , В целом, у клиента есть различные варианты компромисса целостности данных с пропускной способностью.

Управление хэш-таблицей

Для синхронизации доступа к хеш-таблице vbucket каждый входящий поток должен получить блокировку перед доступом к ключевой области хеш-таблицы. Для каждой хеш-таблицы vbucket существует несколько блокировок, каждая из которых отвечает за контроль монопольного доступа к определенной области кета в этой хеш-таблице. Количество областей хеш-таблицы может динамически увеличиваться по мере добавления в хеш-таблицу большего количества документов.

Чтобы контролировать объем памяти хеш-таблицы, поток пейджера Item будет контролировать использование памяти хеш-таблицы. Как только будет достигнут верхний водяной знак, он начнет процесс выселения, чтобы удалить определенное содержимое документа из хеш-таблицы. Только записи, на которые не ссылаются записи в буфере контрольных точек, могут быть удалены, поскольку в противном случае ожидающее обновление (которое существует только в хеш-таблице, но не сохраняется) будет потеряно.

После выселения запись документа все еще остается в хеш-таблице; только содержимое документа будет удалено из памяти, но метаданные все еще там. Процесс выселения прекращается после достижения нижнего водяного знака. Отметка максимума / минимума воды определяется квотой памяти ковша. По умолчанию для отметки максимальной воды установлено значение 75% квоты на ведро, а для отметки низкой воды установлено значение 60% квоты. Эти водяные знаки можно настраивать во время выполнения.

В CouchDb каждый документ связан со сроком действия и будет удален после его истечения. Пейджер Expiry отвечает за отслеживание и удаление документа с истекшим сроком хранения как из хеш-таблицы, так и из механизма хранения (путем планирования операции удаления).

Менеджер контрольных точек

Диспетчер контрольных точек отвечает за утилизацию буфера контрольных точек, в котором находится ожидающий запрос на обновление, который используется двумя последующими процессами, Flusher и TAP-репликатором. Когда все запросы в буфере контрольных точек будут обработаны, буфер контрольных точек будет удален, и будет создан новый.

Репликатор TAP Репликатор

TAP отвечает за миграцию vBucket, а также репликацию vBucket с активного сервера на сервер реплики. Это делается путем распространения последнего измененного документа на соответствующий сервер реплики.

В то время, когда реплика vBucket установлена, весь vBucket необходимо скопировать с активного сервера на пустой целевой сервер реплики следующим образом

  • The in-memory hashtable at the active server will be transferred to the replica server.  Notice that during this period, some data may be updated and therefore the data set transfered to the replica can be inconsistent (some are the latest and some are outdated).
  • Nevertheless, all updates happen after the start of transfer is tracked in the checkpoint buffer.
  • Therefore, after the in-memory hashtable transferred is completed, the TAP replicator can pickup those updates from the checkpoint buffer.  This ensures the latest versioned of changed documents are sent to the replica, and hence fix the inconsistency.
  • Однако кеш хеш-таблицы не содержит всего содержимого документа. Данные также необходимо прочитать из файла vBucket и отправить в реплику. Обратите внимание, что в течение этого периода обновление vBucket будет происходить на активном сервере. Однако, поскольку файл добавляется только, последующее обновление данных не будет мешать процессу копирования vBucket.

После того, как сервер реплики подключился, последующее обновление на активном сервере будет доступно в его буфере контрольных точек, который будет передан репликатором TAP и отправлен на сервер реплики.

Структура хранения CouchDB

Сервер данных определяет интерфейс, в который можно подключить другую структуру хранения. В настоящее время он поддерживает как базу данных SQLite, так и CouchDB. Здесь мы опишем детали CouchDb, который обеспечивает сверхвысокопроизводительный механизм хранения под технологией Couchbase.

Под структурой CouchDB будет один файл на vBucket. Данные записываются в этот файл только для добавления, что позволяет Couchbase делать в основном последовательные записи для обновления и предоставлять наиболее оптимизированные шаблоны доступа для дискового ввода-вывода. Эта уникальная структура хранения объясняет высокую производительность Couchbase на диске для приложений с интенсивной записью.

Следующая диаграмма иллюстрирует модель хранилища и то, как она модифицируется 3 пакетными обновлениями (обратите внимание, что, поскольку обновления являются асинхронными, она выполняется потоком «Flusher» в пакетном режиме).

Поток Flusher работает следующим образом:

1) Забирает
все ожидающие запросы на запись из грязной очереди и дедуплицирует несколько запросов на обновление для одного и того же документа.

2) Сортировать каждый запрос (по ключу) в соответствующий vBucket и открыть соответствующий файл.

3) Добавить следующее в файл vBucket (в следующей последовательной последовательности).

  • Все содержимое документа в таком пакете запроса на запись. Каждый документ будет записан как [length, crc, content] один за другим последовательно.
  • Индекс, в котором хранится сопоставление идентификатора документа с позицией документа на диске (называемый идентификатором BTree)
  • Индекс, в котором хранится сопоставление от порядкового номера обновления до позиции документа на диске. (называется BTree by-seq)

Индекс by-id играет важную роль для поиска документа по его идентификатору. Он организован как B-дерево, где каждый узел содержит диапазон ключей. Для поиска документа по идентификатору нам просто нужно начать с заголовка (который является концом файла), перенести в корневой узел BTree индекса by-id и затем перейти к конечному узлу BTree, который содержит указатель на фактическую позицию документа на диске.

Во время записи аналогичный механизм используется для трассировки до соответствующего узла BTree, который содержит идентификатор измененных документов. Обратите внимание, что в модели только для добавления обновление не происходит на месте, вместо этого мы определяем существующее местоположение и копируем его путем добавления. Другими словами, модифицированный узел BTree необходимо будет скопировать, модифицировать и, наконец, вставить в конец файла, а затем его родительский элемент необходимо изменить, чтобы он указывал на новое местоположение, что инициирует копирование родительских элементов и вставьте в конец файла. То же самое происходит с родителем его родителей и, в конечном итоге, вплоть до корневого узла BTree. Поиск диска может быть в сложности O (logN).

Индекс by-seq используется для отслеживания последовательности обновления действующих документов и используется для целей асинхронного захвата. Когда документ создается, изменяется или удаляется, порядковый номер добавляется в дерево se-seq, а предыдущий узел seq будет удаляться. Поэтому для межсайтовой репликации, просмотра обновлений индекса и сжатия мы можем быстро найти все действующие документы в порядке их последовательности обновления. Когда репликатор vBucket запрашивает список обновлений с определенного времени, он предоставляет последний порядковый номер в предыдущем обновлении, затем система просканирует узел BTree by-seq, чтобы найти весь документ с порядковым номером больше этого, который фактически включает в себя весь документ, который был изменен с момента последней репликации.

Со временем некоторые данные становятся мусором (см. Область серого цвета выше) и становятся недоступными в файле. Следовательно, нам нужен механизм сбора мусора для очистки мусора. Чтобы запустить этот процесс, узел B-Tree by-id и by-seq будет отслеживать размер данных живых документов (тех, которые не являются мусором) под своим поддеревом. Поэтому, изучая корневой узел BTree, мы можем определить размер всех существующих документов в vBucket. Когда соотношение фактического размера и размера файла vBucket падает ниже определенного порогового значения, запускается процесс уплотнения, задачей которого является открытие файла vBucket и копирование оставшихся в живых данных в другой файл.

Технически процесс сжатия открывает файл и читает by-seq BTree в конце файла. Он отслеживает Btree до конечного узла и копирует соответствующее содержимое документа в новый файл. Процесс уплотнения происходит во время обновления vBucket. Однако, поскольку файл добавляется только, новые изменения записываются после корневого каталога BTree, который был открыт для сжатия, поэтому последующее обновление данных не будет мешать процессу сжатия. Когда сжатие завершено, системе необходимо скопировать данные, которые были добавлены с начала сжатия, в новый файл.

Просмотр структуры индекса

Unlike most indexing structure which provide a pointer from the search attribute back to the document.  The CouchDb index (called View Index) is better perceived as a denormalized table with arbitrary keys and values loosely associated to the document.

Such denormalized table is defined by a user-provided map() and reduce() function.

map = function(doc) {
   …
   emit(k1, v1)
   …
   emit(k2, v2)
   …
}

reduce = function(keys, values, isRereduce) {
    if (isRereduce) {
        // Do the re-reduce only on values (keys will be null)
    } else {
        // Do the reduce on keys and values
    }
    // result must be ready for input values to re-reduce

    return result
}

Whenever a document is created, updated, deleted, the corresponding map(doc) function will be invoked (in an asynchronous manner) to generate a set of key/value pairs.  Such key/value will be stored in a B-Tree structure.  All the key/values pairs of each B-Tree node will be passed into the reduce() function, which compute an aggregated value within that B-Tree node.  Re-reduce also happens in non-leaf B-Tree nodes which further aggregate the aggregated value of child B-Tree nodes.

The management server maintains the view index and persisted it to a separate file.

Create a view index is perform by broadcast the index creation request to all machines in the cluster.  The management process of each machine will read its active vBucket file and feed each surviving document to the Map function.  The key/value pairs emitted by the Map function will be stored in a separated BTree index file.  When writing out the BTree node, the reduce() function will be called with the list of all values in the tree node.  Its return result represent a partially reduced value is attached to the BTree node.

The view index will be updated incrementally as documents are subsequently getting into the system.  Periodically, the management process will open the vBucket file and scan all documents since the last sequence number.  For each changed document since the last sync, it invokes the corresponding map function to determine the corresponding key/value into the BTree node.  The BTree node will be split if appropriate.

Underlying, Couchbase use a back index to keep track of the document with the keys that it previously emitted.  Later when the document is deleted, it can look up the back index to determine what those key are and remove them.  In case the document is updated, the back index can also be examined; semantically a modification is equivalent to a delete followed by an insert.

Следующая диаграмма иллюстрирует, как индексный файл представления будет постепенно обновляться с помощью механизма только добавления.

Обработка запросов

Запрос в Couchbase выполняется по индексу представления. Запрос состоит из имени представления, ключа начала и ключа конца. Если функция redu () не определена, результатом запроса будет список значений, отсортированных по ключам в диапазоне ключей. Если определена функция redu (), результатом запроса будет одно агрегированное значение всех ключей в пределах диапазона ключей.

Если в представлении не определена функция redu (), обработка запроса выполняется следующим образом:

  • Клиент отправляет запрос (с представлением, ключом начала / конца) процессу управления любого сервера (в отличие от поиска на основе ключей, нет необходимости искать конкретный сервер).
  • Процесс управления будет передавать запрос другому процессу управления на всех серверах (включая себя) в кластере.
  • Каждый процесс управления (после получения широковещательного запроса) выполняет локальный поиск значения в пределах диапазона ключей, пересекая узел BTree своего файла представления и начинает отправлять результат (автоматически отсортированный по ключу) на исходный сервер.
  • Исходный сервер объединит отсортированный результат и отправит его обратно клиенту.

 Однако, если представление имеет определенную функцию redu (), обработка запроса будет включать вычисление одного агрегированного значения следующим образом:

  • Клиент отправляет запрос (с представлением, ключом начала / конца) процессу управления любого сервера (в отличие от поиска на основе ключей, нет необходимости искать конкретный сервер).
  • Процесс управления будет передавать запрос другому процессу управления на всех серверах (включая себя) в кластере.
  • Каждый процесс управления выполняет локальное уменьшение значения в диапазоне ключей путем обхода узла BTree своего файла представления для вычисления уменьшенного значения диапазона ключей. Если диапазон ключа охватывает узел BTree, можно использовать предварительно вычисленный поддиапазон. Таким образом, функция Reduce может повторно использовать множество частично уменьшенных значений и не требует пересчета каждого значения диапазона ключей с нуля.
  • Исходный сервер выполнит окончательное повторное уменьшение () для всех значений, возвращаемых серверами друг друга, а затем передаст окончательное уменьшенное значение клиенту.

Чтобы проиллюстрировать концепцию повторного сокращения, допустим, что запрос имеет диапазон ключей от A до F.

Вместо того, чтобы вызывать уменьшение ([A, B, C, D, E, F]), система распознает, что узел BTree, содержащий [B, C, D], был предварительно уменьшен, и результат P сохраняется в узле BTree. , так что нужно только вызвать Reduce (A, P, E, F).

Обновлять индекс представления по мере миграции vBucket

Поскольку индекс представления синхронизируется с vBuckets на том же сервере, когда vBucket мигрировал на другой сервер, индекс представления больше не является корректным; те ключ / значение, которые принадлежат перенесенному vBucket, должны быть отброшены, и уменьшенное значение больше не может использоваться.

Чтобы отслеживать vBucket и вводить индекс представления, каждый узел bTree имеет 1024-битную маску, указывающую все vBuckets, которые покрыты в поддереве (то есть: он содержит ключ, выданный из документа, принадлежащего vBucket). Такая битовая маска поддерживается всякий раз, когда обновляется узел bTree.

На уровне сервера глобальная битовая маска используется для указания всех vBuckets, за которые отвечает этот сервер.

При обработке запроса представления «только карта» перед возвратом пары «ключ / значение» для каждой пары «ключ / значение» будет проведена дополнительная проверка, чтобы убедиться, что соответствующий сервер vBucket отвечает за этот сервер.

При обработке запроса представления, имеющего функцию redu (), мы не можем использовать предварительно вычисленное значение Reduce, если узел bTree содержит vBucket, за который сервер не отвечает. В этом случае битовая маска узла bTree сравнивается с глобальной битовой маской. В случае, если они не выровнены, необходимо уменьшить значение уменьшения.

Вот пример, чтобы проиллюстрировать этот процесс

Couchbase — это одна из популярных технологий NOSQL, построенная на прочной технологической основе, рассчитанной на высокую производительность. В этом посте мы рассмотрели ряд таких ключевых особенностей:

  • Балансировка нагрузки между серверами внутри кластера, которая может увеличиваться и уменьшаться в зависимости от условий рабочей нагрузки. Миграция данных может использоваться для восстановления баланса рабочей нагрузки.
  • Asynchronous write provides lowest possible latency to client as it returns once the data is store in memory.
  • Append-only update model pushes most update transaction into sequential disk access, hence provide extremely high throughput for write intensive applications.
  • Automatic compaction ensures the data lay out on disk are kept optimized all the time.
  • Map function can be used to pre-compute view index to enable query access.  Summary data can be pre-aggregated using the reduce function.  Overall, this cut down the workload of query processing dramatically.

Для обзора архитектуры NOSQL в целом и некоторых теоретических основ я написал
блог,
посвященный шаблонам проектирования NOSQL , а также
некоторые фундаментальные различия между SQL и NOSQL.

Что касается других технологий NOSQL, пожалуйста, прочитайте мой другой блог на
MongoDb ,
Cassandra и HBase ,
Memcached

Special, спасибо Дэмиену Кацу и Фрэнку Вейгелю из команды Couchbase, которые предоставляют много подробностей реализации Couchbase.