diff --git a/source/core/read-preference-mechanics.txt b/source/core/read-preference-mechanics.txt index 03d39f2e19c..fc7d8d9251b 100644 --- a/source/core/read-preference-mechanics.txt +++ b/source/core/read-preference-mechanics.txt @@ -35,6 +35,8 @@ settings. The read preference is re-evaluated for each operation. +.. include:: /includes/fact-3.4-added-maxStalenessSeconds.rst + .. include:: /includes/extracts/server-selection-read-preference-replica-sets.rst .. index:: read preference; sharding @@ -48,7 +50,7 @@ Read Preference for Sharded Clusters Load Balancing ~~~~~~~~~~~~~~ -If there is more than one :program:`mongos` instances in the connection +If there is more than one :program:`mongos` instance in the connection seed list, the driver determines which :program:`mongos` is the "closest" (i.e. the member with the lowest average network round-trip-time) and calculates the latency window by adding the @@ -65,7 +67,9 @@ applies the read preference when reading from the shards. Server selection is governed by the :doc:`read preference ` and :setting:`replication.localPingThresholdMs` settings. -.. versionchanged:: 3.0.0 +.. include:: /includes/fact-3.4-added-maxStalenessSeconds.rst + +.. versionchanged:: 3.0 The read preference is re-evaluated for each operation. diff --git a/source/core/read-preference.txt b/source/core/read-preference.txt index 7912345079b..9b3a1de0b9c 100644 --- a/source/core/read-preference.txt +++ b/source/core/read-preference.txt @@ -135,6 +135,59 @@ For more information, see :ref:`read preference background behavior `. See also the :api:`documentation for your driver <>`. +.. _replica-set-read-preference-max-staleness: + +``maxStalenessSeconds`` +----------------------- + +.. versionadded:: 3.4 + +Replica set members can lag behind the :term:`primary` due to network +congestion, low disk throughput, long-running operations, etc. The read +preference ``maxStalenessSeconds`` option lets you specify a maximum +replication lag, or "staleness", for reads from :term:`secondaries +`. When a secondary's estimated staleness exceeds +``maxStalenessSeconds``, the client stops using it for read operations. + +.. include:: /includes/fact-important-maxStalenessSeconds-intended-use.rst + +To use ``maxStalenessSeconds``, all of the +MongoDB instances in your deployment must be using MongoDB 3.4 or +later. If any instances are on an earlier version of MongoDB, the +driver or :program:`mongos` will raise an error. + +You can specify ``maxStalenessSeconds`` with the following read +preference modes: + +- :readmode:`primaryPreferred` +- :readmode:`secondary` +- :readmode:`secondaryPreferred` +- :readmode:`nearest` + +Max staleness is not compatible with mode :readmode:`primary` and only +applies when :ref:`selecting +` a +:term:`secondary` member of a set for a read operation. + +When selecting a server for a read operation with ``maxStalenessSeconds``, clients +estimate how stale each secondary is by comparing the secondary's last +write to that of the primary. The client will then direct the read +operation to a secondary whose estimated lag is less than or equal to +``maxStalenessSeconds``. + +If there is no primary, the client uses the secondary with the most +recent write for the comparison. + +By default, there is no maximum staleness and clients will not consider a +secondary's lag when choosing where to direct a read operation. + +You must specify a ``maxStalenessSeconds`` value of 90 seconds or +longer: specifying a smaller ``maxStalenessSeconds`` value will raise +an error. Clients estimate secondaries' staleness by periodically +checking the latest write date of each replica set member. Since these +checks are infrequent, the staleness estimate is coarse. Thus, clients +cannot enforce a ``maxStalenessSeconds`` value of less than 90 seconds. + .. index:: tag sets .. index:: read preference; tag sets .. _replica-set-read-preference-tag-sets: diff --git a/source/includes/apiargs-method-cursor.readPref-param.yaml b/source/includes/apiargs-method-cursor.readPref-param.yaml index 9132bb043ff..bc62d4e1302 100644 --- a/source/includes/apiargs-method-cursor.readPref-param.yaml +++ b/source/includes/apiargs-method-cursor.readPref-param.yaml @@ -1,5 +1,5 @@ arg_name: param -description: |- +description: | One of the following :term:`read preference` modes: :readmode:`primary`, :readmode:`primaryPreferred`, :readmode:`secondary`, :readmode:`secondaryPreferred`, or :readmode:`nearest` @@ -10,14 +10,44 @@ optional: false position: 1 type: string --- +# TODO: Uncomment this when SERVER-27346 is resolved +# (also add maxStalenessSeconds to the def in ref/meth/cursor.readPref) +# # # # # # # # # # # # # # # # # # # # # +# arg_name: param +# pre: | +# .. versionadded:: 3.4 +# +# description : | +# Specifies, in seconds, how stale a secondary can be before the client +# stops using it for read operations. For details, see: +# :ref:`replica-set-read-preference-max-staleness`. +# +# By default, there is no maximum staleness and clients will not consider a +# secondary's lag when choosing where to direct a read operation. +# +# The minimum {{arg_name}} value is 90 seconds. Specifying a +# value of less than 90 seconds will produce an error. +# +# .. important:: +# To use ``maxStalenessSeconds``, all of the +# MongoDB instances in your deployment must be using MongoDB 3.4 or +# later. If any instances are on an earlier version of MongoDB, the +# driver of :program:`mongos` will raise an error. +# interface: method +# name: maxStalenessSeconds +# operation: cursor.readPref +# optional: true +# position: 2 +# type: non-negative integer +--- arg_name: param -description: |- +description: | A :term:`tag set` used to specify custom read preference modes. For details, see :ref:`replica-set-read-preference-tag-sets`. interface: method name: tagSet operation: cursor.readPref optional: true -position: 2 +position: 3 type: array ... diff --git a/source/includes/extracts-read-preference-modes.yaml b/source/includes/extracts-read-preference-modes.yaml new file mode 100644 index 00000000000..892bc22a6c7 --- /dev/null +++ b/source/includes/extracts-read-preference-modes.yaml @@ -0,0 +1,139 @@ +ref: _maxStalenessSeconds +content: | + When the {{mode}} read preference includes a :ref:`maxStalenessSeconds value + `{{noPrimary}}, + the client estimates how stale each + secondary is by comparing the secondary's last write + to that of the {{compare}}. The client then directs the read operation to a + secondary whose estimated lag is less than or equal to ``maxStalenessSeconds``. + {{readFromSecondary}} +--- +ref: maxStaleness-primaryPreferred +inherit: + file: extracts-read-preference-modes.yaml + ref: _maxStalenessSeconds +replacement: + mode: ":readmode:`primaryPreferred`" + noPrimary: " and there is no primary from which to read" + compare: "secondary with the most recent write" + readFromSecondary: "" +--- +ref: maxStaleness-secondary +inherit: + file: extracts-read-preference-modes.yaml + ref: _maxStalenessSeconds +replacement: + mode: ":readmode:`secondary`" + noPrimary: "" + compare: "primary" + readFromSecondary: | + If there is no primary, the client uses the secondary with the most + recent write for the comparison. +--- +ref: maxStaleness-secondaryPreferred +inherit: + file: extracts-read-preference-modes.yaml + ref: _maxStalenessSeconds +replacement: + mode: ":readmode:`secondaryPreferred`" + noPrimary: "" + compare: "primary" + readFromSecondary: | + If there is no primary, the client uses the secondary with the most + recent write for the comparison. If there are no secondaries with + estimated lag less than or equal to ``maxStalenessSeconds``, the + client directs the read operation to the replica set's primary. +--- +ref: _tagSets +content: | + When the read preference includes :ref:`tag sets + `{{noPrimary}}, + the client attempts to find secondary members that match the + specified tag sets and directs reads to a random secondary from among + the :ref:`nearest group + ` of matching + secondaries. If no secondaries have matching tags, {{behavior}} +--- +ref: tagSets-primaryPreferred +inherit: + file: extracts-read-preference-modes.yaml + ref: _tagSets +replacement: + noPrimary: " and there is no primary from which to read" + behavior: "the read operation produces an error." +--- +ref: tagSets-secondary +inherit: + file: extracts-read-preference-modes.yaml + ref: _tagSets +replacement: + noPrimary: "" + behavior: "the read operation produces an error. [#capacity-planning]_" +--- +ref: tagSets-secondaryPreferred +inherit: + file: extracts-read-preference-modes.yaml + ref: _tagSets +replacement: + noPrimary: "" + behavior: "the client ignores tags and reads from the primary." +--- +ref: _maxStaleness-and-tagSets +content: | + When the read preference includes a ``maxStalenessSeconds`` value + **and** tag sets, the client filters by staleness first and + then by the specified tags.{{nearestBehavior}} +--- +ref: maxStaleness-and-tagSets-general +inherit: + file: extracts-read-preference-modes.yaml + ref: _maxStaleness-and-tagSets +replacement: + nearestBehavior: "" +--- +ref: maxStaleness-and-tagSets-nearest +inherit: + file: extracts-read-preference-modes.yaml + ref: _maxStaleness-and-tagSets +replacement: + nearestBehavior: | + From the remaining :program:`mongod` instances, the client then + randomly directs the read to an instance that falls within the + acceptable latency window. The read preference :ref:`member + selection ` + documentation describes the process in detail. +--- +ref: _secondary-reads-stale-data +content: | + Read operations using the {{mode}} mode may return stale data. Use the + ``maxStalenessSeconds`` option to avoid reading from secondaries + that the client estimates are overly stale. +--- +ref: secondary-reads-stale-data-primaryPreferred +inherit: + file: extracts-read-preference-modes.yaml + ref: _secondary-reads-stale-data +replacement: + mode: ":readmode:`primaryPreferred`" +--- +ref: secondary-reads-stale-data-secondary +inherit: + file: extracts-read-preference-modes.yaml + ref: _secondary-reads-stale-data +replacement: + mode: ":readmode:`secondary`" +--- +ref: secondary-reads-stale-data-secondaryPreferred +inherit: + file: extracts-read-preference-modes.yaml + ref: _secondary-reads-stale-data +replacement: + mode: ":readmode:`secondaryPreferred`" +--- +ref: secondary-reads-stale-data-nearest +inherit: + file: extracts-read-preference-modes.yaml + ref: _secondary-reads-stale-data +replacement: + mode: ":readmode:`nearest`" +... diff --git a/source/includes/extracts-server-selection-read-preference.yaml b/source/includes/extracts-server-selection-read-preference.yaml index c627b25ba06..71c1e595963 100644 --- a/source/includes/extracts-server-selection-read-preference.yaml +++ b/source/includes/extracts-server-selection-read-preference.yaml @@ -14,14 +14,11 @@ content: | * - :readmode:`secondary` - #. The {{actor}} assembles a list of eligible secondary members. - :doc:`Tag sets ` - and :doc:`read concern ` can further + :ref:`maxStalenessSeconds + ` and :doc:`tag + sets ` can further restrict the eligibility of the members. - .. COMMENT To DocsTeam: - In 3.4, will have maxStalenessMS which we'll need to add here. - See https://jira.mongodb.org/browse/DOCS-8723. - #. If the list of eligible members is not empty, the {{actor}} determines which eligible member is the "closest" (i.e. the member with the lowest average network round-trip-time) and @@ -37,15 +34,12 @@ content: | * - :readmode:`nearest` - #. The {{actor}} assembles a list of eligible members (primary and - secondaries). :doc:`Tag sets - ` and :doc:`read - concern` can further limit the + secondaries). :ref:`maxStalenessSeconds + ` and :doc:`tag sets + ` + can further limit the eligibility of the members. - .. COMMENT To DocsTeam: - In 3.4, will have maxStalenessMS which we'll need to add here. - See https://jira.mongodb.org/browse/DOCS-8723. - #. If the list of eligible members is not empty, the {{actor}} determines which eligible member is the "closest" (i.e. the member with the lowest average network round-trip-time) and @@ -68,7 +62,7 @@ content: | * - :readmode:`secondaryPreferred` - - #. Following the server selection process for the for the read + - #. Following the server selection process for the read preference ``secondary``, if a list of eligible secondary members is non-empty, {{actor}} chooses an eligible secondary member. diff --git a/source/includes/fact-3.4-added-maxStalenessSeconds.rst b/source/includes/fact-3.4-added-maxStalenessSeconds.rst new file mode 100644 index 00000000000..303fad2bb9e --- /dev/null +++ b/source/includes/fact-3.4-added-maxStalenessSeconds.rst @@ -0,0 +1,7 @@ +.. versionadded:: 3.4 + MongoDB 3.4 adds the ``maxStalenessSeconds`` read preference option + ``maxStalenessSeconds`` specifies the maximum replication lag, or + "staleness", that a :term:`secondary` can suffer and still be eligible + for read operations. + +.. include:: /includes/fact-important-maxStalenessSeconds-intended-use.rst diff --git a/source/includes/fact-important-maxStalenessSeconds-intended-use.rst b/source/includes/fact-important-maxStalenessSeconds-intended-use.rst new file mode 100644 index 00000000000..736bd1466d6 --- /dev/null +++ b/source/includes/fact-important-maxStalenessSeconds-intended-use.rst @@ -0,0 +1,9 @@ +.. important:: + The ``maxStalenessSeconds`` read preference option is intended for + applications that read from secondaries and want to avoid reading + from a secondary that has fallen overly far behind in replicating + the primary's writes. For example, a secondary might stop + replicating due to a network outage between itself and the primary. + In that case, the client should stop reading from the secondary + until an administrator resolves the outage and the secondary catches + up. diff --git a/source/reference/connection-string.txt b/source/reference/connection-string.txt index b4b6459d06e..089baea81b3 100644 --- a/source/reference/connection-string.txt +++ b/source/reference/connection-string.txt @@ -364,6 +364,36 @@ on a per-connection basis in the connection string: The default value is :readmode:`primary`, which sends all read operations to the replica set's :term:`primary`. + * - .. urioption:: maxStalenessSeconds + + - .. versionadded:: 3.4 + + Specifies, in seconds, how stale a secondary can be before the client + stops using it for read operations. For details, see: + :ref:`replica-set-read-preference-max-staleness`. + + By default, there is no maximum staleness and clients will not consider a + secondary's lag when choosing where to direct a read operation. + + The minimum :urioption:`maxStalenessSeconds` value is 90 + seconds. Specifying a value between 0 and 90 seconds will produce + an error. MongoDB drivers treat a ``maxStalenessSeconds`` value + of ``-1`` as "no max staleness", the same as if + ``maxStalenessSeconds`` is omitted. + + .. important:: + To use ``maxStalenessSeconds``, all of the + MongoDB instances in your deployment must be using MongoDB 3.4 or + later. If any instances are on an earlier version of MongoDB, the + driver or :program:`mongos` will raise an error. + + The following specifies a maxStalenessSeconds value of 120 seconds + with the :readmode:`secondary` read preference mode: + + .. code-block:: none + + mongodb://host.example.com/?readPreference=secondary&maxStalenessSeconds=120 + * - .. urioption:: readPreferenceTags - Specifies a tag set as a comma-separated list of colon-separated diff --git a/source/reference/read-preference.txt b/source/reference/read-preference.txt index 052e69e755f..c86d8994f9d 100644 --- a/source/reference/read-preference.txt +++ b/source/reference/read-preference.txt @@ -43,98 +43,110 @@ Read Preference Modes The :readmode:`primary` read preference mode is not compatible with read preference modes that use :ref:`tag sets - `. If you specify a tag set + ` or :ref:`maxStalenessSeconds + `. + If you specify tag sets or a ``maxStalenessSeconds`` value with :readmode:`primary`, the driver will produce an error. .. readmode:: primaryPreferred In most situations, operations read from the :term:`primary` member of the set. However, if the primary is unavailable, as is the case - during :term:`failover` situations, operations read from secondary - members. + during :term:`failover` situations, operations read from :term:`secondary` + members that satisfy the read preference's ``maxStalenessSeconds`` and + tag sets. + + .. include:: /includes/extracts/maxStaleness-primaryPreferred.rst - When the read preference includes a :ref:`tag set - `, the client reads first from - the primary, if available, and then from :term:`secondaries - ` that match the specified tags. If no secondaries have - matching tags, the read operation produces an error. + .. include:: /includes/extracts/tagSets-primaryPreferred.rst - Since the application may receive data from a secondary, read - operations using the :readmode:`primaryPreferred` mode may return - stale data in some situations. + .. include:: /includes/extracts/maxStaleness-and-tagSets-general.rst + .. include:: /includes/extracts/secondary-reads-stale-data-primaryPreferred.rst + .. readmode:: secondary Operations read *only* from the :term:`secondary` members of the set. If no secondaries are available, then this read operation produces an error or exception. - Most sets have at least one secondary, but there are situations - where there may be no available secondary. For example, a set with - a primary, a secondary, and an :term:`arbiter` may not have any - secondaries if a member is in recovering state or unavailable. - - When the read preference includes a :ref:`tag set - `, the client attempts to - find secondary members that match the specified tag set and directs - reads to a random secondary from among the :ref:`nearest group - `. If no secondaries - have matching tags, the read operation produces an - error. [#capacity-planning]_ + Most replica sets have at least one secondary, but there are + situations where there may be no available secondary. For example, a + replica set with a :term:`primary`, a secondary, and an + :term:`arbiter` may not have any secondaries if a member is in + recovering state or unavailable. - Read operations using the :readmode:`secondary` mode may return stale data. + .. include:: /includes/extracts/maxStaleness-secondary.rst + + .. include:: /includes/extracts/tagSets-secondary.rst + + .. include:: /includes/extracts/maxStaleness-and-tagSets-general.rst + + .. include:: /includes/extracts/secondary-reads-stale-data-secondary.rst .. readmode:: secondaryPreferred In most situations, operations read from :term:`secondary` members, but in situations where the set consists of a single :term:`primary` (and no other members), the read operation will use - the set's primary. + the replica set's primary. + + .. include:: /includes/extracts/maxStaleness-secondaryPreferred.rst - When the read preference includes a :ref:`tag set - `, the client attempts to find - a secondary member that matches the specified tag set and directs - reads to a random secondary from among the :ref:`nearest group - `. If no secondaries - have matching tags, the client ignores tags and reads from the primary. + .. include:: /includes/extracts/tagSets-secondaryPreferred.rst - Read operations using the :readmode:`secondaryPreferred` mode may - return stale data. + .. include:: /includes/extracts/maxStaleness-and-tagSets-general.rst + + .. include:: /includes/extracts/secondary-reads-stale-data-secondaryPreferred.rst .. readmode:: nearest - The driver reads from the *nearest* member of the :term:`set ` according to the :ref:`member selection - ` process. Reads in - the :readmode:`nearest` mode do not consider the member's - *type*. Reads in :readmode:`nearest` mode may read from both - primaries and secondaries. + The driver reads from a member whose network latency falls within + the acceptable latency window. Reads in the :readmode:`nearest` mode + do not consider whether a member is a primary or secondary when + routing read operations: primaries and secondaries are treated + equivalently. The read preference :ref:`member selection + ` documentation + describes the process in detail. Set this mode to minimize the effect of network latency on read operations without preference for current or stale data. + When the read preference includes a :ref:`maxStalenessSeconds value + `, the client estimates + how stale each secondary is by comparing the secondary's last write + to that of the primary, if available, or to the secondary with the + most recent write if there is no primary. The client will then + filter out any secondary whose estimated lag is greater than + ``maxStalenessSeconds`` and randomly direct the read to a remaining + member (primary or secondary) whose network latency falls within the + :ref:`acceptable latency window + `. + If you specify a :ref:`tag set `, the client attempts to - find a replica set member that matches the specified tag set and + find a replica set member that matches the specified tag sets and directs reads to an arbitrary member from among the :ref:`nearest group `. - Read operations using the :readmode:`nearest` mode may return stale - data. + .. include:: /includes/extracts/maxStaleness-and-tagSets-nearest.rst + + .. include:: /includes/extracts/secondary-reads-stale-data-nearest.rst .. note:: All operations read from a member of the nearest group of the replica set that matches the specified read preference mode. The - :readmode:`nearest` mode prefers low latency reads over a - member's :term:`primary` or :term:`secondary` status. + :readmode:`nearest` mode differs in that it prefers low latency + reads over a member's :term:`primary` or :term:`secondary` status. For :readmode:`nearest`, the client assembles a list of - acceptable hosts based on tag set and then narrows that list to - the host with the shortest ping time and all other members of - the set that are within the "local threshold," or acceptable - latency. See :ref:`replica-set-read-preference-behavior-nearest` - for more information. + acceptable hosts based on ``maxStalenessSeconds`` and tag sets + and then narrows that list to the host with the shortest ping + time and all other members of the set that are within the "local + threshold," or acceptable latency. See + :ref:`replica-set-read-preference-behavior-nearest` for more + information. Use Cases ---------