This file is indexed.

/usr/share/doc/python-pymongo-doc/html/examples/high_availability.html is in python-pymongo-doc 2.6.3-1build1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>High Availability and PyMongo &mdash; PyMongo 2.6.3 documentation</title>
    
    <link rel="stylesheet" href="../_static/default.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../',
        VERSION:     '2.6.3',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/underscore.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    <script type="text/javascript" src="../_static/sidebar.js"></script>
    <link rel="top" title="PyMongo 2.6.3 documentation" href="../index.html" />
    <link rel="up" title="Examples" href="index.html" />
    <link rel="next" title="Requests" href="requests.html" />
    <link rel="prev" title="GridFS Example" href="gridfs.html" /> 
  </head>
  <body>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="requests.html" title="Requests"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="gridfs.html" title="GridFS Example"
             accesskey="P">previous</a> |</li>
        <li><a href="../index.html">PyMongo 2.6.3 documentation</a> &raquo;</li>
          <li><a href="index.html" accesskey="U">Examples</a> &raquo;</li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <div class="section" id="high-availability-and-pymongo">
<h1>High Availability and PyMongo<a class="headerlink" href="#high-availability-and-pymongo" title="Permalink to this headline"></a></h1>
<p>PyMongo makes it easy to write highly available applications whether
you use a <a class="reference external" href="http://dochub.mongodb.org/core/rs">single replica set</a>
or a <a class="reference external" href="http://www.mongodb.org/display/DOCS/Sharding+Introduction">large sharded cluster</a>.</p>
<div class="section" id="connecting-to-a-replica-set">
<h2>Connecting to a Replica Set<a class="headerlink" href="#connecting-to-a-replica-set" title="Permalink to this headline"></a></h2>
<p>PyMongo makes working with <a class="reference external" href="http://dochub.mongodb.org/core/rs">replica sets</a> easy. Here we&#8217;ll launch a new
replica set and show how to handle both initialization and normal
connections with PyMongo.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">Replica sets require server version <strong>&gt;= 1.6.0</strong>. Support
for connecting to replica sets also requires PyMongo version <strong>&gt;=
1.8.0</strong>.</p>
</div>
<div class="admonition-see-general-mongodb-documentation admonition seealso">
<p class="first admonition-title">See also</p>
<p class="admonition-title">See general MongoDB documentation</p>
<p class="last"><a class="reference external" href="http://dochub.mongodb.org/core/rs" name="connecting-to-a-replica-set"><em>rs</em></a></p>
</div>
<div class="section" id="starting-a-replica-set">
<h3>Starting a Replica Set<a class="headerlink" href="#starting-a-replica-set" title="Permalink to this headline"></a></h3>
<p>The main <a class="reference external" href="http://dochub.mongodb.org/core/rs">replica set documentation</a> contains extensive information
about setting up a new replica set or migrating an existing MongoDB
setup, be sure to check that out. Here, we&#8217;ll just do the bare minimum
to get a three node replica set setup locally.</p>
<div class="admonition warning">
<p class="first admonition-title">Warning</p>
<p class="last">Replica sets should always use multiple nodes in
production - putting all set members on the same physical node is
only recommended for testing and development.</p>
</div>
<p>We start three <tt class="docutils literal"><span class="pre">mongod</span></tt> processes, each on a different port and with
a different dbpath, but all using the same replica set name &#8220;foo&#8221;. In
the example we use the hostname &#8220;morton.local&#8221;, so replace that with
your hostname when running:</p>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>hostname
morton.local
<span class="nv">$ </span>mongod --replSet foo/morton.local:27018,morton.local:27019 --rest
</pre></div>
</div>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>mongod --port 27018 --dbpath /data/db1 --replSet foo/morton.local:27017 --rest
</pre></div>
</div>
<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>mongod --port 27019 --dbpath /data/db2 --replSet foo/morton.local:27017 --rest
</pre></div>
</div>
</div>
<div class="section" id="initializing-the-set">
<h3>Initializing the Set<a class="headerlink" href="#initializing-the-set" title="Permalink to this headline"></a></h3>
<p>At this point all of our nodes are up and running, but the set has yet
to be initialized. Until the set is initialized no node will become
the primary, and things are essentially &#8220;offline&#8221;.</p>
<p>To initialize the set we need to connect to a single node and run the
initiate command. Since we don&#8217;t have a primary yet, we&#8217;ll need to
tell PyMongo that it&#8217;s okay to connect to a slave/secondary:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">pymongo</span> <span class="kn">import</span> <span class="n">MongoClient</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span> <span class="o">=</span> <span class="n">MongoClient</span><span class="p">(</span><span class="s">&quot;morton.local:27017&quot;</span><span class="p">,</span> <span class="n">slave_okay</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
</pre></div>
</div>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last">We could have connected to any of the other nodes instead,
but only the node we initiate from is allowed to contain any
initial data.</p>
</div>
<p>After connecting, we run the initiate command to get things started
(here we just use an implicit configuration, for more advanced
configuration options see the replica set documentation):</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">admin</span><span class="o">.</span><span class="n">command</span><span class="p">(</span><span class="s">&quot;replSetInitiate&quot;</span><span class="p">)</span>
<span class="go">{u&#39;info&#39;: u&#39;Config now saved locally.  Should come online in about a minute.&#39;,</span>
<span class="go"> u&#39;info2&#39;: u&#39;no configuration explicitly specified -- making one&#39;, u&#39;ok&#39;: 1.0}</span>
</pre></div>
</div>
<p>The three <tt class="docutils literal"><span class="pre">mongod</span></tt> servers we started earlier will now coordinate
and come online as a replica set.</p>
</div>
<div class="section" id="id1">
<h3>Connecting to a Replica Set<a class="headerlink" href="#id1" title="Permalink to this headline"></a></h3>
<p>The initial connection as made above is a special case for an
uninitialized replica set. Normally we&#8217;ll want to connect
differently. A connection to a replica set can be made using the
normal <a class="reference internal" href="../api/pymongo/mongo_client.html#pymongo.mongo_client.MongoClient" title="pymongo.mongo_client.MongoClient"><tt class="xref py py-meth docutils literal"><span class="pre">MongoClient()</span></tt></a> constructor, specifying
one or more members of the set. For example, any of the following
will create a connection to the set we just created:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">MongoClient</span><span class="p">(</span><span class="s">&quot;morton.local&quot;</span><span class="p">,</span> <span class="n">replicaset</span><span class="o">=</span><span class="s">&#39;foo&#39;</span><span class="p">)</span>
<span class="go">MongoClient([u&#39;morton.local:27019&#39;, &#39;morton.local:27017&#39;, u&#39;morton.local:27018&#39;])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">MongoClient</span><span class="p">(</span><span class="s">&quot;morton.local:27018&quot;</span><span class="p">,</span> <span class="n">replicaset</span><span class="o">=</span><span class="s">&#39;foo&#39;</span><span class="p">)</span>
<span class="go">MongoClient([u&#39;morton.local:27019&#39;, u&#39;morton.local:27017&#39;, &#39;morton.local:27018&#39;])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">MongoClient</span><span class="p">(</span><span class="s">&quot;morton.local&quot;</span><span class="p">,</span> <span class="mi">27019</span><span class="p">,</span> <span class="n">replicaset</span><span class="o">=</span><span class="s">&#39;foo&#39;</span><span class="p">)</span>
<span class="go">MongoClient([&#39;morton.local:27019&#39;, u&#39;morton.local:27017&#39;, u&#39;morton.local:27018&#39;])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">MongoClient</span><span class="p">([</span><span class="s">&quot;morton.local:27018&quot;</span><span class="p">,</span> <span class="s">&quot;morton.local:27019&quot;</span><span class="p">])</span>
<span class="go">MongoClient([&#39;morton.local:27019&#39;, u&#39;morton.local:27017&#39;, &#39;morton.local:27018&#39;])</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">MongoClient</span><span class="p">(</span><span class="s">&quot;mongodb://morton.local:27017,morton.local:27018,morton.local:27019&quot;</span><span class="p">)</span>
<span class="go">MongoClient([&#39;morton.local:27019&#39;, &#39;morton.local:27017&#39;, &#39;morton.local:27018&#39;])</span>
</pre></div>
</div>
<p>The nodes passed to <a class="reference internal" href="../api/pymongo/mongo_client.html#pymongo.mongo_client.MongoClient" title="pymongo.mongo_client.MongoClient"><tt class="xref py py-meth docutils literal"><span class="pre">MongoClient()</span></tt></a> are called
the <em>seeds</em>. If only one host is specified the <cite>replicaset</cite> parameter
must be used to indicate this isn&#8217;t a connection to a single node.
As long as at least one of the seeds is online, the driver will be able
to &#8220;discover&#8221; all of the nodes in the set and make a connection to the
current primary.</p>
</div>
<div class="section" id="handling-failover">
<h3>Handling Failover<a class="headerlink" href="#handling-failover" title="Permalink to this headline"></a></h3>
<p>When a failover occurs, PyMongo will automatically attempt to find the
new primary node and perform subsequent operations on that node. This
can&#8217;t happen completely transparently, however. Here we&#8217;ll perform an
example failover to illustrate how everything behaves. First, we&#8217;ll
connect to the replica set and perform a couple of basic operations:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">db</span> <span class="o">=</span> <span class="n">MongoClient</span><span class="p">(</span><span class="s">&quot;morton.local&quot;</span><span class="p">,</span> <span class="n">replicaSet</span><span class="o">=</span><span class="s">&#39;foo&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">test</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">save</span><span class="p">({</span><span class="s">&quot;x&quot;</span><span class="p">:</span> <span class="mi">1</span><span class="p">})</span>
<span class="go">ObjectId(&#39;...&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">find_one</span><span class="p">()</span>
<span class="go">{u&#39;x&#39;: 1, u&#39;_id&#39;: ObjectId(&#39;...&#39;)}</span>
</pre></div>
</div>
<p>By checking the host and port, we can see that we&#8217;re connected to
<em>morton.local:27017</em>, which is the current primary:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">host</span>
<span class="go">&#39;morton.local&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">port</span>
<span class="go">27017</span>
</pre></div>
</div>
<p>Now let&#8217;s bring down that node and see what happens when we run our
query again:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">find_one</span><span class="p">()</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="gr">pymongo.errors.AutoReconnect</span>: <span class="n">...</span>
</pre></div>
</div>
<p>We get an <a class="reference internal" href="../api/pymongo/errors.html#pymongo.errors.AutoReconnect" title="pymongo.errors.AutoReconnect"><tt class="xref py py-class docutils literal"><span class="pre">AutoReconnect</span></tt></a> exception. This means
that the driver was not able to connect to the old primary (which
makes sense, as we killed the server), but that it will attempt to
automatically reconnect on subsequent operations. When this exception
is raised our application code needs to decide whether to retry the
operation or to simply continue, accepting the fact that the operation
might have failed.</p>
<p>On subsequent attempts to run the query we might continue to see this
exception. Eventually, however, the replica set will failover and
elect a new primary (this should take a couple of seconds in
general). At that point the driver will connect to the new primary and
the operation will succeed:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">find_one</span><span class="p">()</span>
<span class="go">{u&#39;x&#39;: 1, u&#39;_id&#39;: ObjectId(&#39;...&#39;)}</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">host</span>
<span class="go">&#39;morton.local&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">port</span>
<span class="go">27018</span>
</pre></div>
</div>
</div>
<div class="section" id="mongoreplicasetclient">
<h3>MongoReplicaSetClient<a class="headerlink" href="#mongoreplicasetclient" title="Permalink to this headline"></a></h3>
<p>Using a <a class="reference internal" href="../api/pymongo/mongo_replica_set_client.html#pymongo.mongo_replica_set_client.MongoReplicaSetClient" title="pymongo.mongo_replica_set_client.MongoReplicaSetClient"><tt class="xref py py-class docutils literal"><span class="pre">MongoReplicaSetClient</span></tt></a> instead
of a simple <a class="reference internal" href="../api/pymongo/mongo_client.html#pymongo.mongo_client.MongoClient" title="pymongo.mongo_client.MongoClient"><tt class="xref py py-class docutils literal"><span class="pre">MongoClient</span></tt></a> offers two key features:
secondary reads and replica set health monitoring. To connect using
<a class="reference internal" href="../api/pymongo/mongo_replica_set_client.html#pymongo.mongo_replica_set_client.MongoReplicaSetClient" title="pymongo.mongo_replica_set_client.MongoReplicaSetClient"><tt class="xref py py-class docutils literal"><span class="pre">MongoReplicaSetClient</span></tt></a> just provide a
host:port pair and the name of the replica set:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">pymongo</span> <span class="kn">import</span> <span class="n">MongoReplicaSetClient</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">MongoReplicaSetClient</span><span class="p">(</span><span class="s">&quot;morton.local:27017&quot;</span><span class="p">,</span> <span class="n">replicaSet</span><span class="o">=</span><span class="s">&#39;foo&#39;</span><span class="p">)</span>
<span class="go">MongoReplicaSetClient([u&#39;morton.local:27019&#39;, u&#39;morton.local:27017&#39;, u&#39;morton.local:27018&#39;])</span>
</pre></div>
</div>
<div class="section" id="secondary-reads">
<span id="id2"></span><h4>Secondary Reads<a class="headerlink" href="#secondary-reads" title="Permalink to this headline"></a></h4>
<p>By default an instance of MongoReplicaSetClient will only send queries to
the primary member of the replica set. To use secondaries for queries
we have to change the <a class="reference internal" href="../api/pymongo/index.html#pymongo.read_preferences.ReadPreference" title="pymongo.read_preferences.ReadPreference"><tt class="xref py py-class docutils literal"><span class="pre">ReadPreference</span></tt></a>:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">db</span> <span class="o">=</span> <span class="n">MongoReplicaSetClient</span><span class="p">(</span><span class="s">&quot;morton.local:27017&quot;</span><span class="p">,</span> <span class="n">replicaSet</span><span class="o">=</span><span class="s">&#39;foo&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">test</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">pymongo.read_preferences</span> <span class="kn">import</span> <span class="n">ReadPreference</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">read_preference</span> <span class="o">=</span> <span class="n">ReadPreference</span><span class="o">.</span><span class="n">SECONDARY_PREFERRED</span>
</pre></div>
</div>
<p>Now all queries will be sent to the secondary members of the set. If there are
no secondary members the primary will be used as a fallback. If you have
queries you would prefer to never send to the primary you can specify that
using the <tt class="docutils literal"><span class="pre">SECONDARY</span></tt> read preference:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">read_preference</span> <span class="o">=</span> <span class="n">ReadPreference</span><span class="o">.</span><span class="n">SECONDARY</span>
</pre></div>
</div>
<p>Read preference can be set on a client, database, collection, or on a
per-query basis, e.g.:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">collection</span><span class="o">.</span><span class="n">find_one</span><span class="p">(</span><span class="n">read_preference</span><span class="o">=</span><span class="n">ReadPreference</span><span class="o">.</span><span class="n">PRIMARY</span><span class="p">)</span>
</pre></div>
</div>
<p>Reads are configured using three options: <strong>read_preference</strong>, <strong>tag_sets</strong>,
and <strong>secondary_acceptable_latency_ms</strong>.</p>
<p><strong>read_preference</strong>:</p>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">PRIMARY</span></tt>: Read from the primary. This is the default, and provides the
strongest consistency. If no primary is available, raise
<a class="reference internal" href="../api/pymongo/errors.html#pymongo.errors.AutoReconnect" title="pymongo.errors.AutoReconnect"><tt class="xref py py-class docutils literal"><span class="pre">AutoReconnect</span></tt></a>.</li>
<li><tt class="docutils literal"><span class="pre">PRIMARY_PREFERRED</span></tt>: Read from the primary if available, or if there is
none, read from a secondary matching your choice of <tt class="docutils literal"><span class="pre">tag_sets</span></tt> and
<tt class="docutils literal"><span class="pre">secondary_acceptable_latency_ms</span></tt>.</li>
<li><tt class="docutils literal"><span class="pre">SECONDARY</span></tt>: Read from a secondary matching your choice of <tt class="docutils literal"><span class="pre">tag_sets</span></tt> and
<tt class="docutils literal"><span class="pre">secondary_acceptable_latency_ms</span></tt>. If no matching secondary is available,
raise <a class="reference internal" href="../api/pymongo/errors.html#pymongo.errors.AutoReconnect" title="pymongo.errors.AutoReconnect"><tt class="xref py py-class docutils literal"><span class="pre">AutoReconnect</span></tt></a>.</li>
<li><tt class="docutils literal"><span class="pre">SECONDARY_PREFERRED</span></tt>: Read from a secondary matching your choice of
<tt class="docutils literal"><span class="pre">tag_sets</span></tt> and <tt class="docutils literal"><span class="pre">secondary_acceptable_latency_ms</span></tt> if available, otherwise
from primary (regardless of the primary&#8217;s tags and latency).</li>
<li><tt class="docutils literal"><span class="pre">NEAREST</span></tt>: Read from any member matching your choice of <tt class="docutils literal"><span class="pre">tag_sets</span></tt> and
<tt class="docutils literal"><span class="pre">secondary_acceptable_latency_ms</span></tt>.</li>
</ul>
<p><strong>tag_sets</strong>:</p>
<p>Replica-set members can be <a class="reference external" href="http://www.mongodb.org/display/DOCS/Data+Center+Awareness">tagged</a> according to any
criteria you choose. By default, MongoReplicaSetClient ignores tags when
choosing a member to read from, but it can be configured with the <tt class="docutils literal"><span class="pre">tag_sets</span></tt>
parameter. <tt class="docutils literal"><span class="pre">tag_sets</span></tt> must be a list of dictionaries, each dict providing tag
values that the replica set member must match. MongoReplicaSetClient tries each
set of tags in turn until it finds a set of tags with at least one matching
member. For example, to prefer reads from the New York data center, but fall
back to the San Francisco data center, tag your replica set members according
to their location and create a MongoReplicaSetClient like so:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">rsc</span> <span class="o">=</span> <span class="n">MongoReplicaSetClient</span><span class="p">(</span>
<span class="gp">... </span>    <span class="s">&quot;morton.local:27017&quot;</span><span class="p">,</span>
<span class="gp">... </span>    <span class="n">replicaSet</span><span class="o">=</span><span class="s">&#39;foo&#39;</span>
<span class="gp">... </span>    <span class="n">read_preference</span><span class="o">=</span><span class="n">ReadPreference</span><span class="o">.</span><span class="n">SECONDARY</span><span class="p">,</span>
<span class="gp">... </span>    <span class="n">tag_sets</span><span class="o">=</span><span class="p">[{</span><span class="s">&#39;dc&#39;</span><span class="p">:</span> <span class="s">&#39;ny&#39;</span><span class="p">},</span> <span class="p">{</span><span class="s">&#39;dc&#39;</span><span class="p">:</span> <span class="s">&#39;sf&#39;</span><span class="p">}]</span>
<span class="gp">... </span><span class="p">)</span>
</pre></div>
</div>
<p>MongoReplicaSetClient tries to find secondaries in New York, then San Francisco,
and raises <a class="reference internal" href="../api/pymongo/errors.html#pymongo.errors.AutoReconnect" title="pymongo.errors.AutoReconnect"><tt class="xref py py-class docutils literal"><span class="pre">AutoReconnect</span></tt></a> if none are available. As an
additional fallback, specify a final, empty tag set, <tt class="docutils literal"><span class="pre">{}</span></tt>, which means &#8220;read
from any member that matches the mode, ignoring tags.&#8221;</p>
<p><strong>secondary_acceptable_latency_ms</strong>:</p>
<p>If multiple members match the mode and tag sets, MongoReplicaSetClient reads
from among the nearest members, chosen according to ping time. By default,
only members whose ping times are within 15 milliseconds of the nearest
are used for queries. You can choose to distribute reads among members with
higher latencies by setting <tt class="docutils literal"><span class="pre">secondary_acceptable_latency_ms</span></tt> to a larger
number. In that case, MongoReplicaSetClient distributes reads among matching
members within <tt class="docutils literal"><span class="pre">secondary_acceptable_latency_ms</span></tt> of the closest member&#8217;s
ping time.</p>
<div class="admonition note">
<p class="first admonition-title">Note</p>
<p class="last"><tt class="docutils literal"><span class="pre">secondary_acceptable_latency_ms</span></tt> is ignored when talking to a
replica set <em>through</em> a mongos. The equivalent is the <a class="reference external" href="http://docs.mongodb.org/manual/reference/mongos/#cmdoption-mongos--localThreshold">localThreshold</a> command
line option.</p>
</div>
</div>
<div class="section" id="health-monitoring">
<h4>Health Monitoring<a class="headerlink" href="#health-monitoring" title="Permalink to this headline"></a></h4>
<p>When MongoReplicaSetClient is initialized it launches a background task to
monitor the replica set for changes in:</p>
<ul class="simple">
<li>Health: detect when a member goes down or comes up, or if a different member
becomes primary</li>
<li>Configuration: detect changes in tags</li>
<li>Latency: track a moving average of each member&#8217;s ping time</li>
</ul>
<p>Replica-set monitoring ensures queries are continually routed to the proper
members as the state of the replica set changes.</p>
<p>It is critical to call
<a class="reference internal" href="../api/pymongo/mongo_replica_set_client.html#pymongo.mongo_replica_set_client.MongoReplicaSetClient.close" title="pymongo.mongo_replica_set_client.MongoReplicaSetClient.close"><tt class="xref py py-meth docutils literal"><span class="pre">close()</span></tt></a> to terminate
the monitoring task before your process exits.</p>
</div>
</div>
</div>
<div class="section" id="high-availability-and-mongos">
<span id="mongos-high-availability"></span><h2>High Availability and mongos<a class="headerlink" href="#high-availability-and-mongos" title="Permalink to this headline"></a></h2>
<p>An instance of <a class="reference internal" href="../api/pymongo/mongo_client.html#pymongo.mongo_client.MongoClient" title="pymongo.mongo_client.MongoClient"><tt class="xref py py-class docutils literal"><span class="pre">MongoClient</span></tt></a> can be configured
to automatically connect to a different mongos if the instance it is
currently connected to fails. If a failure occurs, PyMongo will attempt
to find the nearest mongos to perform subsequent operations. As with a
replica set this can&#8217;t happen completely transparently, Here we&#8217;ll perform
an example failover to illustrate how everything behaves. First, we&#8217;ll
connect to a sharded cluster, using a seed list, and perform a couple of
basic operations:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">db</span> <span class="o">=</span> <span class="n">MongoClient</span><span class="p">(</span><span class="s">&#39;morton.local:30000,morton.local:30001,morton.local:30002&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">test</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">save</span><span class="p">({</span><span class="s">&quot;x&quot;</span><span class="p">:</span> <span class="mi">1</span><span class="p">})</span>
<span class="go">ObjectId(&#39;...&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">find_one</span><span class="p">()</span>
<span class="go">{u&#39;x&#39;: 1, u&#39;_id&#39;: ObjectId(&#39;...&#39;)}</span>
</pre></div>
</div>
<p>Each member of the seed list passed to MongoClient must be a mongos. By checking
the host, port, and is_mongos attributes we can see that we&#8217;re connected to
<em>morton.local:30001</em>, a mongos:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">host</span>
<span class="go">&#39;morton.local&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">port</span>
<span class="go">30001</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">is_mongos</span>
<span class="go">True</span>
</pre></div>
</div>
<p>Now let&#8217;s shut down that mongos instance and see what happens when we run our
query again:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">find_one</span><span class="p">()</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="gr">pymongo.errors.AutoReconnect</span>: <span class="n">...</span>
</pre></div>
</div>
<p>As in the replica set example earlier in this document, we get
an <a class="reference internal" href="../api/pymongo/errors.html#pymongo.errors.AutoReconnect" title="pymongo.errors.AutoReconnect"><tt class="xref py py-class docutils literal"><span class="pre">AutoReconnect</span></tt></a> exception. This means
that the driver was not able to connect to the original mongos at port
30001 (which makes sense, since we shut it down), but that it will
attempt to connect to a new mongos on subsequent operations. When this
exception is raised our application code needs to decide whether to retry
the operation or to simply continue, accepting the fact that the operation
might have failed.</p>
<p>As long as one of the seed list members is still available the next
operation will succeed:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">test</span><span class="o">.</span><span class="n">find_one</span><span class="p">()</span>
<span class="go">{u&#39;x&#39;: 1, u&#39;_id&#39;: ObjectId(&#39;...&#39;)}</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">host</span>
<span class="go">&#39;morton.local&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">port</span>
<span class="go">30002</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">db</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">is_mongos</span>
<span class="go">True</span>
</pre></div>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper">
  <h3><a href="../index.html">Table Of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">High Availability and PyMongo</a><ul>
<li><a class="reference internal" href="#connecting-to-a-replica-set">Connecting to a Replica Set</a><ul>
<li><a class="reference internal" href="#starting-a-replica-set">Starting a Replica Set</a></li>
<li><a class="reference internal" href="#initializing-the-set">Initializing the Set</a></li>
<li><a class="reference internal" href="#id1">Connecting to a Replica Set</a></li>
<li><a class="reference internal" href="#handling-failover">Handling Failover</a></li>
<li><a class="reference internal" href="#mongoreplicasetclient">MongoReplicaSetClient</a><ul>
<li><a class="reference internal" href="#secondary-reads">Secondary Reads</a></li>
<li><a class="reference internal" href="#health-monitoring">Health Monitoring</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#high-availability-and-mongos">High Availability and mongos</a></li>
</ul>
</li>
</ul>

  <h4>Previous topic</h4>
  <p class="topless"><a href="gridfs.html"
                        title="previous chapter">GridFS Example</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="requests.html"
                        title="next chapter">Requests</a></p>
  <h3>This Page</h3>
  <ul class="this-page-menu">
    <li><a href="../_sources/examples/high_availability.txt"
           rel="nofollow">Show Source</a></li>
  </ul>
<div id="searchbox" style="display: none">
  <h3>Quick search</h3>
    <form class="search" action="../search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    <p class="searchtip" style="font-size: 90%">
    Enter search terms or a module, class or function name.
    </p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="requests.html" title="Requests"
             >next</a> |</li>
        <li class="right" >
          <a href="gridfs.html" title="GridFS Example"
             >previous</a> |</li>
        <li><a href="../index.html">PyMongo 2.6.3 documentation</a> &raquo;</li>
          <li><a href="index.html" >Examples</a> &raquo;</li> 
      </ul>
    </div>
    <div class="footer">
        &copy; Copyright 2008 - 2012, 10gen, Inc..
      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.
    </div>
  </body>
</html>