NoSQL - MongoDB. Agility, scalability, performance. I am going to talk about the basis of NoSQL and MongoDB. Why some projects requires RDBMs and another NoSQL databases? What are the pros and cons to use NoSQL vs. SQL? How data are stored and transefed in MongoDB? What query language is used? How MongoDB supports high availability and automatic failover with the help of the replication? What is sharding and how it helps to support scalability?. The newest level of the concurrency - collection-level and document-level.
9. Format for storing documents
JSON-document
{
"firstName“ : “Steve",
"lastName“ : “Brain",
"address“ :
{
"streetAddress“ : “St.Stefan, 101/101",
"city“ : “London",
"postalCode“ : 101101
},
"phoneNumbers“ : [ "123-1234", "123-4567" ]
}
field: value
field: value
field: value
field: value
field: value
field: value
field: value
Documents correspond to native data types in programming languages
Embedded documents and arrays reduce need for expensive joins
10. JSON-format No Normalization
{
_id : “Key123”,
name: “Jane”,
phones: [123, 456],
…
}
Id name
Key123 Jane
Id Phone
1 123
2 456
PersonId PhoneId
Key123 1
Key123 2
Document-oriented data Model
12. • Data storage
• Network transfer format
MongoDB ServerClient App
{ __,
__,
}
Query documents
TCP
Documents in BSON,
exactly as in DB
{ __,
__,
}
Java
Object
Driver
MongoDB and BSON
{"hello": "world"} → "x16x00x00x00x02hellox00x06x00x00x00worldx00x00"
23. SQLTerms MongoDB Aggregation Operators
WHERE $match
GROUP BY $group
HAVING $match
SELECT $project
ORDER BY $sort
LIMIT $limit
SUM() $sum
COUNT() $sum
SQLtoAggregation MappingChart
30. Replication - Arbiter
Data Center
Primary
Votes: 1
Secondary
Votes: 1
Arbiter
Votes: 1
Primary
Votes: 1
Replication:Arbiter
31. Replication:Voting
Replica Set
Primary
Secondary
Priority: 2
Votes: 1
Secondary
Priority:1
Votes: 1
The initiation of a new replica set
A secondary loses contact with a primary
A Primary steps down
Heartbeat
Primary
New Primary election
Best candidate by Priority
Secondary
Priority: 1
Votes: 1
Optime: 13579
Secondary
Priority:1
Votes: 1
Optime: 13888
Best candidate by optime
33. Auto-Sharding
C1 Mongod
C1 Mongod
C1 Mongod
Config Servers
Query Router
MongoS
Application
Mongod
Shard 2
Mongod
Shard 1
Mongod
Shard 3
A - P Q - Z T - ZH - SA - GShard key ->
Sharded cluster
34. Auto-Sharding: Sharded ClusterTest and
Production Architecture
Sharded Cluster Test Architecture Production Cluster Architecture
Config server Config server
Router
mongos Router
mongos
Router
mongos
Router
mongos
…
Shard 1
Config server
Config server
Shard 1… … Shard N
Replica Set Replica SetReplica Set
36. Auto-Sharding : Shard key
Avoid monotonically Increasing Shard Keys
Avoid immutable Shard Keys
Use a hashed shard key or select a field that does not increase
or decrease monotonically
You cannot change a shard key after sharding the collection.
Mongod
Shard 2
Mongod
Shard 1
Mongod
Shard 3
[1 … 100] [101… 200] [201…*]
Write load for
the last shard
Write load evenly
37. Auto-Sharding : Tips and Best Practices
Only shard big collections
Pick shard key carefully
Try do not use monotonically increasing shard key values
Adding shards is fairly easy but isn’t instantaneous
Connect to mongos except for dba. Put the mongos on default
port
When configure system, use server names instead of ip
addresses
38. Processes and Machines Layout – Example 1
Shard 2Shard 1 Shard 3
Replica Set – “testset1” Replica Set – “testset2” Replica Set – “testset3”
S1 S2
P
S1 S2
P
Server 1 Server 2 Server 3
P P PS1 S1S1
S2 S2 S2
Config Config Config
Mongos Mongos Mongos
S1 S2
P
SystemconfigurationProcesses&MachinesLayout
39. Processes and Machines Layout – Example 2
Shard 2Shard 1 Shard 3
Replica Set – “testset1” Replica Set – “testset2” Replica Set – “testset3”
S1 S2
P
S1 S2
P
S1 S2
P
SystemconfigurationProcesses&MachinesLayout
P S1 S2
P S1
S2 P
S1 S2
Config
ConfigConfig
Mongos
Mongos
MongosMongos
Mongos Mongos
40. Pluggable Storage Engines
MongoDB Query Language
MongoDB Data Model
Security
Management
MMAPv1 WiredTiger In-Memory HDFS Other…
Applications: Ad Service, Archive…
43. Full Index Support
• Default index. Field: _id.
• Index on sub-documents. Field: name.lastName.
• Compound indexes. Fields: age and sex.
• Index on array. Field: characterization.
• TTL indexes. Field: visitDate.
• Geospatial indexes. Field: location.
• Text indexes. Field: description.
{
_id: …,
name: {
lastName: “Smith”,
firstName: “John”},
age: 65,
sex: male,
characterization:
[ “smart”, “kind”, …],
visitDate: 06 Jan 2013,
location: {x:…, y: …},
description: “The text for
indexes.”
….
}
44. • No Consistency between collections
• Indexes take up a lot of RAM (All available)
• Size-limitations
• No Stored Procedures
• NoTransaction
• NoTriggers
• Limited set of usefulTools
Disadvantages
47. New Pluggable Storage Engines
MongoDB Query Language
MongoDB Data Model
Security
Management
MMAPv1 WiredTiger In-Memory
3rd party
Engines
Applications: Ad Service, Sensor Data, Content
Repo, RealTime Analytics, Mobile App
Encrypted
MongoDB Storage Engines
Default
MongoDB 3.2
48. In-Memory (Beta)
•Handle ultra-high
throughput with low
latency and high
availability
•Based on WiredTiger SE
•Achieve data durability
with replica set members
running disk-backed SE
Encrypted
•Reduces the management
and performance overhead
of external encryption
•Based on WiredTiger SE
•Requires MongoDB
Enterprise Advanced
•AES-256, FIPS 140-2
encryption options
New Pluggable Storage Engines
MongoDB 3.2
В качестве определяющих характеристик для больших данных отмечают «три V»: объём (англ. volume, в смысле величины физического объёма), скорость (англ. velocity в смыслах как скорости прироста, так и необходимости высокоскоростной обработки и получения результатов), многообразие (англ. variety, в смысле возможности одновременной обработки различных типов структурированных и полуструктурированных данных)[5][6].
После некоторого этапа анализа и проектирования, решили создать систему, которая будет содержать достаточный набор возможностей для нормальной и удобной работы с базой данных, но не будет содержать фишки, которые тем или иным образом будут усложнять процесс масштабируемости, уменьшать скорость отклика и будут влиять на отказоустойчивость.
Если нарисовать график соответствия, по оси х будут ‘Features’, а по оси y соответственно ‘Scale & Speed’, то мы увидим, что реляционные базы данных имеют огромное количество плюшек, но соответственно скорость и процесс масштабируемости достаточно мал. В тоже время Монго занимает позицию c достаточным количеством плюшек, которые сильно не влияют на масштабируемость и соответственно скорость. На графике можно выделить интервал для так называемого пространства No-SQL. Отсюда и пошёл этот термин, что МонгоДБ является No-SQL базой данных.
No SQL – немного странное название, но многие говорят лучше хоть как-то назвать, чем не иметь имени вовсе
Key Features
High Performance
MongoDB provides high performance data persistence. In particular,
Support for embedded data models reduces I/O activity on database system.
Indexes support faster queries and can include keys from embedded documents and arrays.
High Availability
To provide high availability, MongoDB’s replication facility, called replica sets, provide:
automatic failover.
data redundancy.
A replica set is a group of MongoDB servers that maintain the same data set, providing redundancy and increasing data availability.
Automatic Scaling
MongoDB provides horizontal scalability as part of its core functionality.
Automatic sharding distributes data across a cluster of machines.
Replica sets can provide eventually-consistent reads for low-latency high throughput deployments.
В последнее время, компании активно использующие хранилища баз данных, переходят от реляционных моделей хранения данных, к так называемым No-SQL моделям (иными словами документно-ориентированным моделям).
Основная причина ухода от реляционной модели хранения данных – это получение возможности выполнить процесс масштабирования как можно проще и дешевле.
Предположим в прошлом, у нас был маломощный сервер базы данных. В процессе работы нам потребовалось больше мощности. Традиционный подход в получении большей мощности это переход на более мощную машину (покупка более мощного сервера или наращивание мощности за счёт дополнительных планок памяти, процессоров и т.д.). Соответственно такой подход является гораздо более дорогостоящим. По прошествии какого-то времени нам опять потребовалось бы больше ресурсов и естественным образом, компания способная оплатить расходы на покупку более мощного сервера, приобретёт его.
Этот подход является классическим способ масштабируемости и называется вертикальной масштабируемостью. Этот подход подразумевает добавление ресурсов к единственному узлу в системе, обычно привлекая дополнительные CPU или оперативную память, либо же покупку более мощного оборудования целиком.
Альтернативой вертикальной масштабируемости является горизонтальная масштабируемость. Данный подход используют огромное количество специалистов, включая разработчиков МонгоДБ. Этот подход подразумевает добавление большего количества узлов в кластер, для получения необходимой мощности. К примеру, расширить систему с 1-ой машины до 7-ми. Сотни маломощных компьютеров могут быть сконфигурированы в кластеры с целью получить агрегированную мощь, которая очень часто превышает мощность компьютеров используемых для научных исследований. Проблема данного подхода состоит в том, что каждый отдельный узел должен общаться друг с другом и их работа должна быть хорошо скоординирована, а также система должна быть максимально отказоустойчива. Отказоустойчивость подразумевает продолжение нормальной работы кластера базы данных, если один или несколько серверов выходят из строя.
Одной из целей в проектировании Монго была цель создать базу данных максимально масштабируемую, с высокой скоростью отклика и максимально отказоустойчивую. На практике оказалось достаточно сложно построить такую систему используя всем известные плюшки реляционных баз данных, такие как транзакции, Joins и другое.
В реляционных базах данных Запись – это строка таблицы, а в Монго базе Запись – это документ в формате JSON, а если быть более точным, то в бинарном JSON, т.е. BSON.
Когда стал вопрос выбора формата для документов, отталкивались от нескольких вариантов. Был Вариант с XML, но он оказался тяжелым для человеческого восприятия и решили использовать JSON (Java Script Object Notation), который представляет объект в удобочитаемом виде.
Как известно JSON (JavaScript Object Notation) – это формат для обмена данными. Он легко воспринимается человек для чтения и написания, а также он является очень эффективным форматом для кодирования и декодирования для большинства языков программирования из-за использования С типов данных.
Мы все в той или иной степени сталкивались с этим форматом, поэтому пример приведённый на слайде, не требует детального рассмотрения.
Представление данных в JSON-формате избавило от необходимости создавать операции на подобии JOIN, т.к. все необходимые данные хранятся в одном документе. К тому же JOINs, слишком ресурса-затратная операция.
JSON-формат используется не только для хранения данных, а также этот формат используется, как язык запросов таких как CRUD-операции. Об этом чуточку попозже.
На следующем слайде, мы рассмотрим такой же JSON-документ и его же представления в реляционных базах данных.
Безусловно, проектирую новый подход хранения данных, оборачиваешься на уже существующие системы в поисках удачных решений, которые полезны и удобны в использовании.
При анализе всех возможностей реляционных баз данных, от которых уже совсем не хочется отказываться, разработчики Монго ДБ столкнулись лишь с 2-мя глобальными проблемами. Этот JOINS и сложные транзакции. Если рассматривать пример с несколькими сотнями или тысячами сервером в одном кластере, то не сложно догадаться, что время отклика на общение серверов в одном кластере может быть весьма маленьким, но если количество сервером огромное, то и время затраченное на JOIN данных или осуществление транзакций или отката транзакций может быть значительным.
К сожалению, группа разработчиков Монго ДБ, не смогли придумать достаточно хорошего решения для реализации этих возможностей в распределённой системе, но смогли предложить альтернативу.
Если JOINs является одной из проблем сделать систему масштабируемой, тогда давайте уйдём от концепции реляционности данных и будем использовать совершенно другую модель хранения данных. Key/value словарь хорошо вписался в документно-ориентированный подход хранения данных. Документно-ориентированная модель представляет собой иерархическую структуру пар ключ/значение.
Сразу же стал вопрос о формате хранения документов. Первый на ум пришёл xml-формат. Для программирования – это не самый удобный формат, который бывает достаточно сложным для человеческого восприятия и достаточно тяжеловесным. Альтернатива xml-формату – JSON-формат (Java Script Object Notation).
Т.к. JOINs является ресурсоёмкой и тяжелой операцией, а данные могут быть иерархическими, пришла на ум идея, уйти от нормализации данных и сделать вложенную структуру данных. Т.е. документы могут содержать поддокументы с данными. Т.е. вместо необходимости делать объединение таблиц, как это было раньше, мы имеем все данные немедленно.
Из всего делаем вывод, что документ в рамках МонгоДБ – это базовая единица хранения данных.
При новом подходе хранения данных отпадает необходимость использовать тяжеловесные JOIN-операции, а также в использовании транзакции. Можно сказать что привычные нам транзакции отсутствуют в МонгоДБ, но из-за документно-ориентированного подхода хранения данных запись данных в один документ является атомарной операцией.
Пользователи успешно используют MongoDB в системах электронной коммерции, но приложения которые требуют записи множества данных с возможностью отката изменений для них использование MongoDB – нереальная операция.
JSON-формат используется не только для хранения данных, а также как форма запросов. Но об этом чуточку позже.
MongoDB концептуально то же самое, что и обычная, привычная нам база данных.
1. Внутри Монго может быть ноль или более баз данных.
Каждая база данных является контейнером для прочих сущностей.
2. База данных может иметь ноль или более коллекций. Коллекция очень схожа с таблицами.
3. Коллекции состоят из нуля или более документов. Документ, своего рода это запись или «строка» в терминах реляционных баз данных.
4. Документ состоит из одного или более полей, которые в свою очередь подобны «колонкам». Одно маленькое отступление, о котором мы поговорим чуть позже – это то, что документы хранятся в формате BSON – расширение JSON.
Термины хоть и близки к своим «реляционным», но не полностью идентичны им.
К примеру, в реляционных базах данных «колонки» определяются на уровне «таблицы», в то время как документ-ориентированные базы данных определяют «поля» на уровне «документа». Это значит, что любой документ внутри коллекции может иметь свой собственный уникальный набор полей. И это делает Монго базу без схемной.
Подводя итог, скажу, MongoDB хранит и передает данные в BSON-формате. Это внутренний формат для хранения данных.
Рассмотрим пример хранения и передачи документов.
Предположим у нас есть Монго сервер и клиентское приложение у которого настроен конекшн к серверу. В Базе Данных на Монго сервере у нас есть ряд коллекций с документами, документы хранятся в формате BSON, т.е. в бинарном представлении. Когда клиент делает запрос в БД, данные в том же формате, без каких-либо модификаций, байт по байту начинают передаваться по сети к клиенту. Точная копия документа, в итоге, попадает в оперативную память на клиенте. Для дальнейшей работы драйвер для клиентского языка преобразует BSON-документ, в объектный вид, понятный языку программирования.
BSON-документ также можно представить как сериализованный формат данных. Драйвер, естественно, может преобразовывать объекты в обратный формат.
Аналогом группировки данных в МонгоДБ является агрегация.
Агрегация в Монго, может быть выполнена тремя способами, каждый из которых имеет свои сильный стороны и предназначение в определенных ситуациях.
Агрегационные пайплайны. Документы из коллекции проходят ряд pipelines и в конечном счёте получается запрашиваем результат.
Map-Reduce. Способ агрегации, который очень полезен, когда агрегация не может быть выполнена при помощи агрегационного Фреймворка. Этот способ состоит из 2-х этапов, каждый из которых описывается функциями JavaScript.
Одноцелевые агрегационные операции. Существуют операции для подсчёта количества определенных документов, для возвращения уникальных значений полей, группировка данных на основании значений полей. Обычно подобные операции не очень гибкие, по сравнению с агрегационными пайплайнами и map-reduce функциями.
Отличительной особенностью aggregation pipelines и map-reduce является то, что они могут работать с так называемыми sharded коллекциями. Об этом чуточку попозже, но идея состоят и в том, что МонгоДБ позволяет распределять хранение данных одной коллекции по нескольким серверам и перечисленные выше способы агрегации могут с ними работать, а вот последний вариант агрегации не умеет работать с подобными коллекциями.
Aggregation Pipeline – это целый фреймворк для выполнения задач агрегации данных, смоделированный по модели пайплайнов. Каждый оператор пайплайна трансформирует документы. Результатом агрегационного пайплайна является документ или набор документов.
Aggregation Pipeline поддерживают работу с sharded коллекциями.
Map-Reduce является альтернативой aggregation pipelines, но из-за своей сложности используется в основном тогда, когда при помощи агрегационного фреймворка невозможно выполнить ту или иную агрегацию.
Агрегация способом Map-Reduce происходит в 2 этапа. Первый этап это маппинг, когда создаются наборы ключей и массив значений по ключам, а следующий этап выполняет операции агрегации, к примеру суммирует значения и возвращает полученный результат.
Этапы агрегации способом Map-Reduce описываются JavaScript.
Как и aggregation pipeline, map-reduce может работать с sharded коллекциями.
!!! По результатам перформанса Aggregation Pipeline более производителен, чем map-reduce, но map-reduce более гибкий способ агрегации.
Map/Reduce – в терминах SQL тоже самое, что и агрегирующие функции, такие как COUNT, MAX, MIN, которые работают с группированными данными. В отличии от SQL, Map/Reduce позволяет более гибкую модель по агрегации. Её даже называют целым framework для агрегации данных.
Пока нам нужно усвоить, что агрегация в Монго ДБ происходит в 2 этапа: Map и Reduce. Каждый из этих этапов описываются JavaScript, что даёт нам невероятную гибкость.
Давайте рассмотрим один из самых простых примеров агрегации – подсчет количества одинаковых фигур во всех документах коллекции shapes.
Рассмотрим коллекцию с 4-мя документами. В каждом документе есть набор фигур (пусть это будет массив из фигур).
Нам нужно проанализировать фигуры в каждом из документов, для этого мы выполняем функцию Mapping, которая формирует пары ключ, значение. Ключом в нашем примере будет фигура, а значением будет 1, т.к. нам нужно подчитать кол-во одинаковых фигур.
Так для первого документа….
После операции Map, наступает черед функции Reduce. На вход эта функция получает массив ключей и значений, а на выходе получается финальный результат. Своего рода словарь уникальных ключей и их значений.
Так для треугольников на выходе мы получим значение = 2, для квадратов = 4 и т.д.
Далее хотелось бы показать, как выглядят функции Map и Reduce.
Emit() – создаёт ключ-значение
Reduce получает на вход уникальный ключ и массив его значений.
Что же такое репликация?
Репликация это процесс синхронизации данных между несколькими серверами.
Для чего же она нужна?
Предположим у нас есть БД, на продакшн сервере желательно хранить где-то бекап этой БД или зеркало, на случай падения сервера. А ещё лучше хранить 2 копии. А самое главное на разных серверах, с целью сделать систему отказоустойчивой.
Набор mongod процессов с одними и теми же данным, называется Replica Set.
Одной из главных целей репликации – это обеспечение отказоустойчивости системы и хранение бекапов данных.
Рассмотрим процесс репликации более детально.
Предположим у на есть база данных, для этой базы данных мы решили хранить несколько копий данных и решили что 3-х хранилищ достаточно. В данном случае так называемый Replication Factor будет равен 3.
Основная база данных называется Primary, а её копии Secondary. По умолчанию запись и чтение данных клиентом может выполняться только в Primary, но возможно настроить систему таким образом, что бы чтение выполнялось и из Secondary БД.
Наш клиент выполняет запись в базу данных и соответственно пишет только в Primary. Все изменения данных записываются в так называемый oplog-файл, который и хранит историю за некоторый период, из которого Secondary и наполняют свои хранилища.
Процесс репликации данных происходит асинхронно.
В каждый момент времени среди набора реплик один только сервер является Primary, все остальные – Secondary.
Существует два отличительных качества в MongoDB репликации.
Во-первых – это автоматическое восстановление системы после отказа, а во-вторых это автоматический процесс восстановления данных после отказа.
Предположим у нас есть Replica Set, клиент подключается к Primary БД и начинает в неё вносить изменения. В какой-то момент времени наш Primary сервер перестаёт быть доступным. Члены Replica Set отсылают запрос друг другу и если ответ не получен в течении 10 секунд, это сервер маркируется как недопустимый.
Когда Primary сервер падает, один из Secondary серверов занимает его место и запись с клиента начинается на вновь выбранный Primary. Выбор претендента на Primary из существующих Secondary серверов происходит голосованием. Голосование выполняется по установленному свойству priority. Priority : 0 – говорит о том, что этот сервер не может претендовать на роль Primary.
Драйвер на клиенте осведомлён о всех изменениях в конфигурации и перенаправляет запрос на запись на нужный сервер. Автоматически система применяет новую конфигурацию и репликация происходит из нового Primary. Этот процесс называется Automatic Failover (Автоматическое восстановление системы при отказе).
В какой-то момент времени упавший сервер восстановлен, но его позиция уже занята и он приобретает статус Secondary сервера и происходит автоматический процесс восстановления данных.
При падении Primary-сервера, выбор наследника осуществляется голосование оставшихся серверов. На данном слайде представлен пример Реплики с Репликой Фактором = 3, но в некоторых системах, достаточно хранить 1 копию данных. В таком случае, для выполнения правильного голосования добавляют сервер под названием Arbiter, который совсем не хранит данных, а выполняет лишь роль избирателя.
Рассмотрим пример на следующем слайде.
MongoDB implements a readers-writer lock. This means that at any one time, only one client may be writing or any
number of clients may be reading, but that reading and writing cannot occur simultaneously.
In standalone and replica sets the lock’s scope applies to a single mongod (page 910) instance or primary instance.
In a sharded cluster, locks apply to each individual shard, not to the whole cluster.
If your MongoDB deployment uses TLS/SSL, MongoDB will encrypt all communication between replica set members. See http://docs.mongodb.org/manual/tutorial/configure-ssl for more informa-
tion. As with all MongoDB components, run arbiters in trusted network environments.
Существует два отличительных качества в MongoDB репликации.
Во-первых – это автоматическое восстановление системы после отказа, а во-вторых это автоматический процесс восстановления данных после отказа.
Предположим у нас есть Replica Set, клиент подключается к Primary БД и начинает в неё вносить изменения. В какой-то момент времени наш Primary сервер перестаёт быть доступным. Члены Replica Set отсылают запрос друг другу и если ответ не получен в течении 10 секунд, это сервер маркируется как недопустимый.
Когда Primary сервер падает, один из Secondary серверов занимает его место и запись с клиента начинается на вновь выбранный Primary. Выбор претендента на Primary из существующих Secondary серверов происходит голосованием. Голосование выполняется по установленному свойству priority. Priority : 0 – говорит о том, что этот сервер не может претендовать на роль Primary.
Драйвер на клиенте осведомлён о всех изменениях в конфигурации и перенаправляет запрос на запись на нужный сервер. Автоматически система применяет новую конфигурацию и репликация происходит из нового Primary. Этот процесс называется Automatic Failover (Автоматическое восстановление системы при отказе).
В какой-то момент времени упавший сервер восстановлен, но его позиция уже занята и он приобретает статус Secondary сервера и происходит автоматический процесс восстановления данных.
При падении Primary-сервера, выбор наследника осуществляется голосование оставшихся серверов. На данном слайде представлен пример Реплики с Репликой Фактором = 3, но в некоторых системах, достаточно хранить 1 копию данных. В таком случае, для выполнения правильного голосования добавляют сервер под названием Arbiter, который совсем не хранит данных, а выполняет лишь роль избирателя.
Рассмотрим пример на следующем слайде.
MongoDB implements a readers-writer lock. This means that at any one time, only one client may be writing or any
number of clients may be reading, but that reading and writing cannot occur simultaneously.
In standalone and replica sets the lock’s scope applies to a single mongod (page 910) instance or primary instance.
In a sharded cluster, locks apply to each individual shard, not to the whole cluster.
Changed in version 3.0.0: A replica set can have up to 50 members but only 7 voting members. In previous versions, replica sets can have up to 12 members.
Changed in version 3.0.0: Members cannot have votes greater than 1. For details, see 3.0-compatibility-repl-set-config.
Oplog is capped collection. The size of the oplog connection is configurable.
Выборы происходят после инициализации replica set и каждый раз когда Primary сервер становится недоступен.
Primary – единственный член реплики, который может принимать операции записи.
Выборы – это часть процесса восстановления системы после отказа.
Выборы очень важная операция, которая занимает некоторое время. Пока выборы в процессе, replica set существует без Primary сервера и операции записи недоступны.
Факторы и Условия влияющие на выборы
Запрос (тактовый импульс)
Члены Replica Set пингуют друг друга каждые 2 секунды. Если ответ не приходит в течении 10 секунд, член реплики отправивший запрос маркирует сервер как недоступный.
Сравнение приоритетов (Priority)
У каждого сервера выставляется такое свойство как priority. При выборе сервера предпочтение отдаётся серверу с наибольшим значением приоритета.
Если значение свойства priority равно 0 – это говорит о том, что сервер не может стать Primary.
Optime
Optime – это временная метка последней операции, которую член реплики применил из oplog-файла. Член реплики не может стать Primary, до тех пор пока у него не будет наиболее последнего optime среди видимых членов replica set.
Connections (Связывание)
Член replica set не может стать Primary пока он не может приконектиться к большинству членов реплики сета. Большинство берётся из общего количества голосов, а не из количество членов реплики.
Механизм Выбора
Replica set инициирует выборы всякий раз, когда primary недоступен: основание новой replica set, secondary потеряли связь с primary, primary понизил свою позицию по любой причине (получил команду replSetStepDown, secondaries has a higher priority, primary cannot contact a majority of the members of the replica set).
Каждый член реплики имеет свой priority, который помогает определить приоритетность стать primary. По умолчанию, каждый член replica set имеет значение 1 для свойства priority, что говорит о том, что все члены реплики имеют одинаковые права занять позицию primary.
Первый член реплики получивший большинство голосов становится primary. Каждый голосующий член реплики имеет свойство votes, которое по умолчанию приравнивается к 1. Можно выставлять другие значение, но лучше не влиять на выбор по средствам votes, а лучше повлиять при помощи priority.
Replica set может содержать до 12 членов, но только 7 из них учувствуют в голосовании.
Свойство state также влияет на выборы. Члены реплики в следующих стейтах участвуют в голосовании: PRIMARY, SECONDARY, RECOVERING, ARBITER, ROLLBACK.
Network Partitions
Network partitions affect the formation of a majority for an election. If a primary steps down and neither portion of the replica set has a majority the set will not elect a new primary. The replica set becomes read-only.
To avoid this situation, place a majority of instances in one data center and a minority of instances in any other data centers combined.
Что же такое Auto-Sharding?
Проблемы с вместимостью данных на сервере и его пропускной способностью возникают время от времени для больших систем.
Для решения эти проблем существует вертикальное и горизонтальное масштабирование, о которых я рассказывала в самом начале.
В двух словах, вертикальное масштабирование предполагает расширение мощности единственного сервера за счёт добавления CPU, ресурсов для хранения данных. Горизонтальное же масштабирование (sharding) распределяет данные по множеству серверов (shards) и вопрос масштабирования решается за счёт добавления дополнительных серверов.
Что же такое shard?
Shard – это независимая база данных. Коллекция этих shards составляет одну большую единую логическую базу данных.
Shard-ом может быть как единый mongod, так и Replica Set.
Данные в шарде хранятся в chunks, который имеют ограниченный размер. По умолчанию размер чанка равен 64 МБ, но его размер конфигурируемый.
Sharding оперирует на уровне коллекции. Множество коллекций в БД могут распределять свои данные по шардам, но также совместно с ними могут хранится коллекции, которые хранят свои данные только на одном шарде (primary shard).
По умолчанию, все коллекции не распределяются по shard-ам. Распределение по шардам начинается тогда, когда задаётся shard key и объем данных превышает допустимый объем в одном chunk.
Важное правило!!! Если объем данных достаточно мал, нет необходимости делить данные по шарды – это можетсильно усложнить систему. В таком случает, достаточным является replica set для единственного mongod сервера.
Рассмотрим пример.
Данные БД распределены по двум шардам. Первый шард, к примеру, хранит документы у которого ключевое поле имеет значение с А-Р, а второй Q-Z.
Когда клиент записывает или запрашивает данные из БД, его запрос направляется на Query Router, который ещё называют mongos. Query Router уже в свою очередь направляет запрос на нужный шард или шарды и возвращает результат.
Предположим место для хранения данных практически исчерпано и приняли решение добавить ещё 1 шард, после перераспределения данных, шарды будут выглядеть следующим образом.
Config servers хранят метаданные о расположении данных по шардам. Query Router использует эту информацию. На продакшн решении должно быть 3 Config сервера.
Config servers хранят метаданные на config базе данных.
Mongos кэширует метаданные из конфиг серверов и используют их для чтения и записи данных в шарды.
При добавлении новых Шардов, MongoDB автоматически распределит данные на новый сервер. Шардинг автоматически балансирует данные и нагрузку по машинам.
Деление данных по шардам осуществляется при помощи shard key, который может быть как одиночный индекс, так и составной индекс коллекции. Монго не сможет создавать chunks и шардинг не будет работать, пока shard key не будет нормально сконфигурирован.
Shard keys могут быть сгенерированы рендомно. Рендомные ключи предполагают оптимальное распределение данные по кластерам.Д ля shard key можно использовать любой field. Поле _id – это наиболее общий shard key. Shard key – это поле которое существует в каждом документе коллекции.
Внутри шарда, Монго порционирует документ в так называемые chunks. Каждый chunk представляет более меньший диапазон документ.
MongoDB автоматически балансирует данные между шардам.
Advantages:
Масштабируемость. Когда данных становится слишком много для одной машины, достаточно лишь добавить ещё одну машину и авто-шардинг автоматически распределит данные на новую машину.
Шарды могут быть размещены на множестве машин, что позволяет распределить данные и нагрузку на несколько машин, повышая тем самым производительность.
Шардинг также обеспечивает дополнительную мощность по распределению нагрузки записи данных.
Добавление новых данных может привести систему к несбалансированности внутри кластера. Для поддержания баланса, MongoDB использует splitting и balancer. Эти два процесса работают в фоновом режиме. Первый делит слишком большой chunk, на более маленькие chunks, а второй выполняет миграцию chunks между шардами для балансировки данных.
Is sharding appropriate for a new deployment?
Sometimes.
If your data set fits on a single server, you should begin with an unsharded deployment.
Converting an unsharded database to a sharded cluster is easy and seamless, so there is little advantage in configuring
sharding while your data set is small.
Still, all production deployments should use replica sets to provide high availability and disaster recovery.
Production Cluster Architecture
In a production cluster, you must ensure that data is redundant and that your systems are highly available. To that end,
a production cluster must have the following components:
• Three config servers. Each config servers must be on separate machines. A single sharded cluster
must have exclusive use of its config servers. If you have multiple sharded clusters, you will need to
have a group of config servers for each cluster.
• Two or more replica sets. These replica sets are the shards. For information on replica sets, see Replication.
• One or more mongos instances. mongos is the routers for the cluster. Typically,
deployments have one mongos instance on each application server. You may also may deploy a
group of mongos instances and use a proxy/load balancer between the application and the mongos.
Sharded Cluster Test Architecture
Warning: Use the test cluster architecture for testing and development only.
For testing and development, you can deploy a minimal sharded clusters cluster. These non-production clusters have
the following components:
• One config server.
• At least one shard. Shards are either replica sets or a standalone mongod instances.
• One mongos instance.
Sharded cluster for production has component requirements to provide redundancy and high availability.
A production cluster has no single point of failure.
Shard key – определяет распределение документов между шардами. Shard key – это indexed field или compound indexed field.
Распределенные документы (группы документов) хранятся в так называемых chunk, размер которых ограничен и по умолчанию равен 64 МБ и может быть изменён. Когда размер chunk доходит до предельного значения, он разбивается на два, и при необходимости мигрирует в нужный шард.
There is no automatic support in MongoDB for changing a shard key after sharding a collection. This reality un-derscores the important of choosing a good shard key
Сущесвуют hashed shared key, которые используют hashed indexes. Это нововведение в Монго ДБ, начина с версии 2.4.
Существует ряд подсказок и best practices
Only shard big collections
Pick shard key carefully
Consider presplitting on a bulk load
Be aware of monotonically increasing shard key values on inserts.
Adding shards is fairly easy but isn’t instantaneous. (take a while to migrate data)
Always connect to mongs except for dba work. Put the mongos on default port (for example).
Use logic config server names than direct ip addresses, because to change server will be easy.
Теперь рассмотрим пример конфигурации системы, которая использует Replica Set, с Replica Factor = 3, а также Sharding или горизонтальное масштабирование.
Большинство replica sets состоит из двух или более mongod сущностей, среди которых хотя бы один задизайнен как главный и остальные как второстепенные члены. Клиент адресует все записи на главный, а второстепенные члены реплики автоматически копируют данные из главного сервера асинхронно.
Рассмотрим, как MongoDB на практике реализует репликацию.
Из предыдущего примера данные БД разбиты на 3 шарда. Шардом может быть единственный процесс mongod, иными словами, данные в единственном экземпляре, а также шардом может быть так называемая Replica Set, когда одни и те же данные имеют зеркала.
В нашем примере, каждый из шардов имеет Primary и Seconary данные.
Что ж в нашем примере у нас 3 набора реплик.
Для трёх шардов мы выделим 3 сервера (на практике, существует даже такое правило: минимальное количество сервером = количеству шардов).
Каждый сервер будет содержат по Мастер Шарду. Далее Оставшиеся mongod зеркала, тоже будут распределены по серверам. Как вы видите мы смешали данные по серверам. Ни один набор реплик не хранится на единственном сервере. Соответственно, если сервер выйдет из строя, приложение по-прежнему будет продолжать работать.
К тому же каждый сервер должен содержать сервер конфигурации (с метаданными, где и что хранится) и mongos – сервер маршрутизации, который обрабатывает запросы с уровня приложения и определяет месторасположение данных.
Это один из пример архитектуры Replica Set, но не существует универсальной архитектуры под все случаи.
Репликация данных в MongoDB добавляет избыточность данных, помогает обеспечить высокую доступность, упрощает задачу бекапа и может увеличивать мощность процедуры чтения.
MongoDB репликация асинхронная. Это значит, что данные синхронизируются между репликами не в момент непосредственного изменения данных, а отложено, через какое-то время. В этом есть плюс, не тратится время на репликацию в момент изменения данных (insertы происходят быстрее), а также минус: в определенные моменты времени данные между репликами могут быть не согласованными.
Большинство продакшн решений используют репликацию.
Replica Set в MongoDB обеспечивает автоматическую отказоустойчивость. Если главный сервер падает, оставшиеся члены автоматически выберут новый главный среди второстепенных.
На данный момент MongoDB поддерживает две основные парадигмы репликации: master-slave и replica sets.
Master-Slave
-----------------
Применяется во многих СУБД. Несколько сервером, один из них мастер, два слейва. Удалить и писать в БД можно только в мастер-сервере, а читать, как из мастера, так и из слейвов.
Такая схема полезна, когда у нашей системы много запросов на получение данных.
Replica Sets
===========
В наборе реплик, также используют мастер, только 1 в каждый момент времени. Отличие от предыдущего подхода в автоматическйо смене мастера, если это необходимо.
!!!! Особое значение набор реплик приобретает совместно с шардингом. В этом случае один и тот же шард можно реплицировать на несколько сервером, обеспечивая отличную отказоустойчивость. Управляющий процесс mongos самостоятельно определяет к какой из реплик осуществлять запрос, осуществляя тем самым автоматическую балансировку.
Each shard is a REPLICA SET.
Shard could be a single mongod (bad idea), a master-slave setup (better idea), or a replica set (best idea).
Replica Set Factor = 3.
Processes and machines layout
В этой схеме у нас есть 10 физических машин. Этого количества более чем достаточно, для того, что бы расположить на каждой машине по одному источнику данных.
Далее необходимо сконфигурировать месторасположение Config серверов – это может быть любой физический сервер. Желательно расположить Config-сервера на машинах, которые не хранят данные из Primary shard, т.е. данные первого шарда. Естественно, что располагать их на одной машины совсем не имеет смысла.
Как я уже рассказывала ранее, mongos (Router) – это прослойка между клиентом и шардами и их количество может быть любым, поэтому вполне возможен вариант, что каждый сервер будет содержать по Mongos.
Последняя машина, может оставаться в качестве резерва, а может быть сконфигурирован, например, для Config.
Through the use of a pluggable storage architecture, MongoDB can be extended with new capabilities, and configured for optimal use of specific hardware architectures. This approach significantly reduces developer and operational complexity compared to running multiple databases to power applications with unique requirements. Users can leverage the same MongoDB query language, data model, scaling, security and operational tooling across different applications, each powered by different pluggable MongoDB storage engines.
MongoDB 3.0 ships with two supported storage engines, both of which can coexist within a single MongoDB replica set, making it easy to evaluate and migrate between them:
•The default MMAPv1 engine, an improved version of the engine used in prior MongoDB releases.
•The new WiredTiger storage engine. For manyapplications, WiredTiger's more granular concurrency
MongoDB 3.0 ships with two supported storage engines: MMAPv1 engine and the new WiredTiger storage engine and one experimental in-memory storage. Both engines (MMAPv1 and WiredTiger) can coexist within the same MongoDB replica set, making it simple to evaluate and migrate between them.
The default MMAPv1 engine, an improved version of the engine used in prior MongoDB releases. The newest version supports collection level concurrency control.
The new WiredTigner storage engine. More granular concurrency control and native compression provide benefits in lower storage costs, greater hardware utilization, higher throughput, and more predictable performance.
In-Memory is an experimental In-Memory storage engine ?????
Other engines under development by MongoDB: RocksDB Key-Value engine, HDFS storage engine and a FusionIO engine.
Одним из действительно полезных новшеств (фич) в Монго являеся GridFS.
Это файловая система внутри MongoDB была разработана для хранения файлов, особенно тех, которые имеют размер более 16 МБ.
Почему 16 МБ, потомучто BSON объекты ограничены размером в 16 МБ, и GridFS помогает хранит файлы в нескольких чанках. По умолчанию размер чанка – 256 Кб.
GridFS разбивает большие файлы на управляемые кусочки (чанки). Эти чанки сохраняются в коллекцию (fs.chunks), а потом метаданные о файле в другую коллекцию (fs.files). Когда вы запрашиваете файл, GridFS запрашивает коллекцию fs.chunks и возвращает файл по одному кусочку.
Разбиение файлов на кусочки, даёт нам огромную производительности при получении не целого файла, а по кусочкам.
К примеру, вы сохранили видео-файл размер более 2 Гб, для того, что бы его получить, вам нужно загрузить все 2 Гб данных в память, а если у Вас будет файл размер 10, 25 Гб, никакой оперативной памяти не хватит на него. А GridFS решает эту проблему, при помощи возврата запрошенной картинки по чанкам.
К достоинствам подхода GridFS можно отнести
Используя репликацию или автошардинг ваши GridFS файлы также будут реплицированы и разбиты по шардам.
Нет необходимости переживать за ограничения ОС, как недопустимые имена файлов или большое количество файлов в одной директории.
GridFS также полезно использовать не только для файлов которые больше 16 Мб, а также для файлов, которые вы не хотите загружать в память.
Для документов в MongoDB коллекции, ты должен использовать GridFS для хранения файлов с размером более 16 МБ.
///// TODO: DESCRIBE EACH INDEX.
Fundamentally, indexes in MongoDB are similar to indexes in other database systems. MongoDB supports
indexes on any field or sub-field contained in documents within a MongoDB collection.
For all collections, MongoDB creates the default _id index. You cannot delete the index on _id.
All indexes in MongoDB are secondary indexes. You can create indexes on any field within any document or sub-document. Additionally, you can create compound indexes with multiple fields, so that a single query can match multiple components using the index while scanning fewer whole documents.
MongoDB supports “compound indexes,” where a single index structure holds references to multiple fields within a collection’s documents.
Indexes store references to fields in either ascending or descending order.
If you index a field that contains an array, MongoDB indexes each value in the array separately, in a “multikey index.”
Hashed indexes maintain entries with hashes of the values of the indexed field.
By default, creating an index blocks all other operations on a database. When building an index, the databases that
hold those collections are not available for read or write operations until the index build completes. Any operation that
requires a read or write lock on all databases (e.g. listDatabases) will wait for the foreground index build to complete.
For potentially long running index building operations consider the background operation so that the MongoDB
database remains available during the index building operation.
Warning: As in all unique indexes, if a document does not have the indexed field, MongoDB will include it in
the index with a “null” value.
If subsequent fields do not have the indexed field, and you have set {dropDups: true}, MongoDB will
remove these documents from the collection when creating the index.
Index Features:
TTL indexes are special indexes that MongoDB can use to automatically remove documents from a collection after a certain amount of time. The indexed field must be a date type.
MongoDB provides “geospatial indexes” to support location-based and other similar queries in a two dimensional coordinate systems. To create a geospatial index, your documents must have a coordinate pair.
Text index. MongoDB provides text indexes to support the search of string content in documents of a collection. text indexes are case-insensitive and can include any field that contains string data. text indexes drop language-specific stop words (e.g. in English, “the,” “an,” “a,” “and,” etc.) and uses simple language-specific suffix stemming.
When developing your indexing strategy you should have a deep understanding of:
• The application’s queries.
• The relative frequency of each query in the application.
• The current indexes created for your collections.
• Which indexes the most common queries use.
To determine whether a query is a covered query, use the explain() method. If the explain() output displays true for the indexOnly field, the query is covered by an index, and MongoDB queries only that index to match the query and return the results.
For the fastest processing, ensure that your indexes fit entirely in RAM so that the system can avoid reading the index
from disk.
Конечно же MongoDB обладает рядом недостатков. Среди этих недостатков можно выделить следующие пункты.
1) Незрелый. MongoDB очень молодой продукт. Он существует всего 5 лет на рынке. В нём встречаются баги, появляются новые фичи. Его можно использовать в продакшене, но очень осторожно. Этот недостаток, можно смело сделать плюсом, так как темп разработки высокий, проект пишут не только волонтеры, но и компания людей на полной занятости. Можно быстро рассчитывать на быстрый багфикс, помощь в решении проблем. Также доступна коммерческая поддержка.
Индексы в MongoDB хранятся в памяти. С одной стороны, это увеличивает скорость поиска, если индексов не много, но если же их много, они могут быстро занять весь допустимый объем ресурсов. Но также, если на сервере много RAM, тем выше производительность базы данных.
Ограничение на размер документа – 16МБ, а также на 32-битных машинах, максимальный размер одной БД – 2 Гб.
Отсутствие транзакций. Атомарные операции поддерживаются только на уровне одного документа.
MongoDB содержит драйвера для работы с ним для множества языков программирования.
MongoDB.org поддерживает языки С, С++, Java, Perl, Python, соответственно .NET C# и другие.
Ещё больше языков поддерживает Community, среди них Delphi, ActionScript, Objectve C, MatLab и другие.