103

我一直在网上搜索为 MongoDB Java 驱动程序配置 MongoOptions 的最佳实践,除了 API 之外,我没有想出太多东西。这个搜索是在我遇到“com.mongodb.DBPortPool$SemaphoresOut: Out of semaphores to get db connection”错误之后开始的,通过增加连接/乘数我能够解决这个问题。我正在寻找链接或您在为生产配置这些选项时的最佳实践。

2.4驱动的选项包括: http ://api.mongodb.org/java/2.4/com/mongodb/MongoOptions.html

  • 自动连接重试
  • 每个主机的连接数
  • 连接超时
  • 最大等待时间
  • 套接字超时
  • threadsAllowedToBlockForConnectionMultiplier

较新的驱动程序有更多选择,我也有兴趣了解这些。

4

1 回答 1

162

更新到 2.9 :

  • autoConnectRetry只是意味着驱动程序将在意外断开连接后自动尝试重新连接到服务器。在生产环境中,您通常希望将此设置为 true。

  • connectionsPerHost是单个 Mongo 实例(它是单例的,因此通常每个应用程序都有一个)可以建立到 mongod/mongos 进程的物理连接的数量。在撰写本文时,即使实际查询吞吐量很低,Java 驱动程序最终也会建立此数量的连接(换句话说,您将看到 mongostat 中的“conn”统计数据上升,直到每个应用服务器达到此数量)。

    在大多数情况下,无需将其设置为高于 100,但此设置是“测试并查看”的内容之一。请注意,您必须确保将其设置得足够低,以便与服务器的连接总数不超过

    db.serverStatus().connections.available

    在生产中,我们目前有 40 个。

  • 连接超时。顾名思义,在连接尝试中止之前,驱动程序将等待的毫秒数。将超时设置为较长的​​时间(15-30 秒),除非有现实的、预期的机会,否则这将妨碍成功的连接尝试。通常,如果连接尝试花费的时间超过几秒钟,您的网络基础设施就无法实现高吞吐量。

  • 最大等待时间。线程将等待连接在连接池上可用的毫秒数,如果没有及时发生则引发异常。保持默认。

  • 套接字超时。标准套接字超时值。设置为 60 秒 (60000)。

  • 线程AllowedToBlockForConnectionMultiplier。connectionsPerHost 的乘数,表示如果池当前已用尽,则允许等待连接变为可用的线程数。这是将导致“com.mongodb.DBPortPool$SemaphoresOut: Out of semaphores to get db connection”异常的设置。一旦此线程队列超过threadsAllowedToBlockForConnectionMultiplier 值,它将抛出此异常。例如,如果connectionsPerHost 为10 且此值为5,则在引发上述异常之前,最多有50 个线程可以阻塞。

    如果您预计可能会导致大型队列的吞吐量峰值会暂时增加此值。正是出于这个原因,我们目前的价格为 1500。如果您的查询负载始终超过服务器,您应该相应地改善您的硬件/扩展情况。

  • 阅读偏好(已更新,2.8+)用于确定默认读取首选项并替换“slaveOk”。通过类工厂方法之一设置 ReadPreference。最常见设置的完整描述可以在这篇文章的末尾找到

  • w(更新,2.6+)这个值决定了写入的“安全性”。当此值为 -1 时,无论网络或数据库错误如何,写入都不会报告任何错误。WriteConcern.NONE 是合适的预定义 WriteConcern。如果 w 为 0,则网络错误将导致写入失败,但 mongo 错误不会。这通常被称为“即发即弃”写入,并且应该在性能比一致性和持久性更重要时使用。在此模式下使用 WriteConcern.NORMAL。

    如果将 w 设置为 1 或更高,则认为写入是安全的。安全写入执行写入并通过向服务器发出请求来跟踪它,以确保写入成功或如果没有成功则检索错误值(换句话说,它会在您写入后发送 getLastError() 命令)。请注意,在此 getLastError() 命令完成之前,连接将被保留。由于这一点和附加命令,吞吐量将显着低于 w <= 0 的写入。aw 值恰好为 1 时,MongoDB 保证在您将写入发送到的实例上写入成功(或可验证失败)。

    在副本集的情况下,您可以使用更高的值来告诉 MongoDB 在返回之前将写入发送到副本集的至少“w”个成员(或者更准确地说,等待将您的写入复制到“w”个成员)。您还可以将 w 设置为字符串“majority”,它告诉 MongoDB 执行对大多数副本集成员的写入 (WriteConcern.MAJORITY)。通常,您应该将其设置为 1,除非您需要原始性能(-1 或 0)或复制写入(>1)。大于 1 的值对写入吞吐量有相当大的影响。

  • 同步。启用时强制 mongo 在每次写入后刷新到磁盘的持久性选项。我从来没有遇到过与写积压相关的持久性问题,因此我们在生产中将此设置为 false(默认值)。

  • j * (新 2.7+) *。布尔值,当设置为 true 时强制 MongoDB 在返回之前等待成功的日志组提交。如果您启用了日记功能,则可以启用此功能以获得额外的耐用性。请参阅http://www.mongodb.org/display/DOCS/Journaling以查看日志记录为您带来了什么(以及您可能想要启用此标志的原因)。

ReadPreference 如果您使用副本集,ReadPreference 类允许您配置路由到哪些 mongod 实例查询。以下选项可用:

  • ReadPreference.primary():所有读取仅发送到 repset 主要成员。如果您要求所有查询返回一致的(最近写入的)数据,请使用此选项。这是默认设置。

  • ReadPreference.primaryPreferred():如果可能,所有读取都转到 repset 主要成员,但如果主要节点不可用,则可以查询辅助成员。因此,如果主节点变得不可用,读取最终会变得一致,但前提是主节点不可用。

  • ReadPreference.secondary():所有读取都转到辅助 repset 成员,主要成员仅用于写入。仅当您可以接受最终一致的读取时才使用此选项。尽管一个 repset 可以拥有的(投票)成员的数量有限制,但可以使用其他 repset 成员来提高读取性能。

  • ReadPreference.secondaryPreferred():如果其中任何一个可用,则所有读取都将转到辅助 repset 成员。主要成员专门用于写入,除非所有次要成员都不可用。除了回退到主要成员进行读取之外,这与 ReadPreference.secondary() 相同。

  • ReadPreference.nearest():读取到数据库客户端可用的最近的 repset 成员。仅在最终一致的读取是可接受的情况下使用。最近的成员是客户端和各个 repset 成员之间延迟最低的成员。由于忙碌的成员最终会有更高的延迟,这也应该自动平衡读取负载,尽管根据我的经验,如果成员延迟相对一致,次要(首选)似乎做得更好。

注意:以上所有方法都具有相同方法的标签启用版本,这些版本改为返回 TaggableReadPreference 实例。副本集标签的完整描述可以在这里找到:副本集标签

于 2011-06-29T13:49:00.927 回答