Статьи

MongoDB Драйвер Советы и хитрости: Mongoid 3

Многие из запросов на поддержку, которые мы получаем в MongoLab, представляют собой вопросы о том, как правильно настроить и использовать определенные драйверы MongoDB.

Этот пост является первым из серии, в которой мы планируем подробно рассмотреть каждый из основных драйверов MongoDB. Драйвер, который мы рассмотрим сегодня, — Mongoid, разработанный Дурраном Джорданом (@modetojoy).

В этом посте:

Примечание: мы обновим этот пост, когда Mongoid 4.x будет официально выпущен (см. Журнал изменений ).

Mongoid

Mongoid — картограф объектов документа Ruby (ODM). Для реляционных людей ODM являются эквивалентом MongoDB Object Relational Mappers (ORM). Одна из основных причин, по которой разработчики используют ODM, такие как Mongoid, заключается в том, что он дает им возможность определять схему для своих документов, которую затем можно использовать для сопоставления документов с объектами на их языке программирования. В Mongoid эта функция служит простым переходом для разработчиков Ruby on Rails, привыкших работать с ActiveRecord.

Mongoid и низкоуровневый драйвер Moped, над которым он написан, является одним из основных драйверов языка, не написанных MongoDB, Inc. Однако, поскольку он является самым популярным драйвером Ruby среди пользователей MongoLab, мы получаем много запросы поддержки о том, как правильно настроить и использовать этот драйвер с MongoLab.

Этот пост поможет вам понять, как эффективно настроить и использовать Mongoid в вашем приложении MongoDB.

Примечание. Официальный Ruby-драйвер MongoDB, поддерживаемый MongoDB, Inc., можно найти здесь: http://docs.mongodb.org/ecosystem/drivers/ruby/#ruby-driver.

Простой монгоидный пример

Вы можете найти простой пример подключения, вставки, обновления и запросов с использованием Mongoid в Языковом центре MongoLab .

Готовые к настройке соединения

Мы часто видим, что у пользователей возникают проблемы с подключением к MongoLab с помощью драйвера Mongoid. Основной причиной является почти всегда неправильная конфигурация драйвера, особенно из-за тайм-аутов.

В Mongoid файл mongoid.yml содержит параметры конфигурации драйвера. Ниже приведены рекомендуемые MongoLab настройки для версии 3 Mongoid:

# mongoid 3.x
#
# As discussed in: http://blog.mongolab.com/2014/02/mongodb-driver-tips-tricks-mongoid-3
#
production: 
  sessions:
    default:
      # The standard MongoDB connection URI allows for easy replica set 
      # connection setup. 
      # Use environment variables or a config file to keep your 
      # credentials safe.
      uri: 'mongodb://username:password@host1:port1,host2:port2/database'

      options: 
        # The default consistency is :eventual, which reads from 
        # secondaries when possible. 
        # Strong forces reads to primary. 
        # We recommend using strong consistency.
        consistency: :strong

        # max_retries specifies the number of times to attempt an 
        # operation before giving up.
        max_retries: 30

        # retry_interval specifies the number of seconds to wait before 
        # retrying a single operation.
        retry_interval: 1

        # The default timeout is 5, which is the time in seconds for an 
        # operation to time out.
        # We recommend 15 because it allows for plenty of time in most 
        # operating environments.
        # Mongoid doubles the configured value (known issue) so 15 
        # results in a timeout of 30s.
        # Note that if you have a long-running query (over 30 seconds), 
        # it will time out.
        # See our example for long-running queries in the blog post 
        # referenced above.
        timeout: 15

Дополнительные параметры можно найти здесь .

Примечание: Mongoid 4.x будет иметь несовместимые изменения. Мы обновим этот пост, когда он будет официально выпущен.

Mongoid советы и хитрости

По умолчанию Mongoid читает из вторичных

Mongoid поддерживает только два режима предпочтения чтения MongoDB: основной (согласованность:: сильный) и вторичный (согласованность:: возможный).

Если вы используете настройку согласованности по умолчанию Mongoid, Mongoid будет направлять чтения для вторичных. Это часто нежелательно по ряду причин. В частности, вторичные чтения часто могут привести к:

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

  • Медленное или неудачное чтение во время построения индекса. MongoDB поддерживает только построение индексов переднего плана для вторичных серверов, что блокирует другие операции во время построения индексов. Если вы инициируете построение индекса при работающем развертывании, запросы, отправленные на вторичный сервер, будут зависать.

  • Медленное или неудачное чтение во время резервного копирования или снимков. Большинство методов резервного копирования включают блокировку или остановку вторичного экземпляра MongoDB. Если вы используете вторичные запросы на чтение, которые вы отправляете вторичному, зависнет.

  • Перегруженный первичный, если вторичный узел выходит из строя или становится недоступным. Направление чтения на вторичный сервер увеличивает пропускную способность чтения и снижает нагрузку на первичный. Однако при отказе вторичного узла все операции чтения и записи передаются первичному. Эти дополнительные операции могут значительно увеличить нагрузку и опрокинуть базу данных.

Настройка тайм-аута в конфигурации Mongoid удваивается

В приведенном выше примере файла mongoid.yml с тайм-аутом, установленным на 15, фактическое значение тайм-аута, примененное Mongoid, будет 30 секунд. Вы можете найти подробную информацию на  https://github.com/mongoid/mongoid/issues/3445 .

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

Распространенной ошибкой, которую мы видим с драйвером Mongoid, является ConnectionFailure. Например:

Moped::Errors::ConnectionFailure: Could not connect to a primary node for replica set <Moped::Cluster nodes=[<Moped::Node resolved_address=»ipAddress»>, <Moped::Node resolved_address=»ipAddress»>]>

This error is thrown whenever Mongoid has difficulty making a connection. It’s normal to see this error thrown multiple times in succession as Mongoid will retry the connection creation based on your mongoid.yml settings – specifically the retry_interval.

In many cases the default value of 5 seconds for this timeout will be adequate. But often, users who are running their app with a Platform-as-a-Service (PaaS), such as Heroku, will find that their driver often needs longer to establish a connection to the database, particularly when dynos are just starting up. For this reason we recommend allowing up to 30 sec for connections to become established.

Use the no_timeout option on long operations

Most MongoDB drivers have separate settings for connection timeouts (how long to wait to establish a connection) and socket timeouts (how long to wait for a response from the database when issuing operations, like a query). This can be problematic since you often want a short and finite connection timeout but often you will wait to wait much longer (often indefinitely) for results from queries.

With our recommended connection timeout setting of 30 sec you may find your driver prematurely giving up on queries that take longer than 30 sec.

Luckily, Moped has a no_timeout option that can be used for these particular situations. Revisiting our simple example, the find query can be rewritten as the following to ensure that the cursor will not timeout.

db = Mongoid::Sessions.default                                                      

db[:songs].find({ weeksAtOne: { '$gte' => 10 }}).sort({ decade: 1}).no_timeout.each do |doc|
  puts  "In the #{ doc['decade'] }," +                                              
        " #{ doc['song'] } by #{ doc['artist'] }" +                                 
        " topped the charts for #{ doc['weeksAtOne'] }" +                           
        " straight weeks."                                                          
end      

Be careful managing connections when using Sidekiq

When using Sidekiq (for background processing jobs) in conjunction with Mongoid, it’s important to be aware that each job will prompt the creation of a new connection. At lower numbers this behavior is fine but once you get into thousands of connections you need to use connection pooling, which Mongoid does not directly support. We’ve directed our users to this thread on the issue, which discusses the problems that arise and proposes a solution for reusing connections.

Build the indexes required by DelayedJob Mongoid Backend

The delayed_job_mongoid module issues a findAndModify command on the “delayed_backend_mongoid_jobs” collection and queries on the “run_at” field. As with all MongoDB queries, it’s important to make sure right indexes are in place for optimal performance. Be sure to follow the delayed_job_mongoid installation instructions to create the required indexes.

You’re all set!

We hope this post helps shed light on some of Mongoid’s quirks. If you have any tips and tricks that you’d like to share please post in comments or write to us at support@mongolab.com so we can pass on the knowledge. Be sure to check back when Mongoid 4 is released!