当主人失灵时,从奴隶那里读取复制品(+ pymongo)

时间:2012-02-26 18:45:36

标签: mongodb replication pymongo

似乎使用pymongo,连接将始终尝试从PRIMARY 读取,当它关闭时,会引发套接字错误,直到新的选举过程完成。

鉴于replicSet的目的之一是平衡读取负载,这似乎是一个重大缺陷,除非我在这里错过了一个关键概念。

我提供了slave_ok thingy,但是,只要没有主要的可用,没有读取,更不用说写入了。

我已经在端口8910,8911和8912上启动了3个mongod实例,并且一个接一个地将它们关闭,当最后一个保留时,没有办法从中读取,即使你mongo(cli)让我们阅读。

正在使用的版本:

mongodb: 2.0.2
pymongo: 2.1.1

pymongo控制台输出

>>> collection = Connection("localhost:8910, localhost:8911, localhost:8912", slave_okay=True).testdb['TEST']
>>> len(list(collection.find()))
0
>>> collection.insert({"a": 1})
ObjectId('4f4a491bb9efb72ec8000045')
>>> len(list(collection.find()))
1

取下3个实例中的1个(主要实例),然后......

>>> len(list(collection.find()))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/cursor.py", line 703, in next
    if len(self.__data) or self._refresh():
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/cursor.py", line 666, in _refresh
    self.__uuid_subtype))
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/cursor.py", line 616, in __send_message
    **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/connection.py", line 880, in _send_message_with_response
    sock = self.__socket()
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/connection.py", line 686, in __socket
    sock, from_pool = self.__pool.get_socket(host, port)
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/connection.py", line 165, in get_socket
    self.sock = (pid, self.connect(host, port))
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/connection.py", line 127, in connect
    s.connect((host, port))
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 111] Connection refused
>>> 

选出了新的小学,然后......

>>> len(list(collection.find()))
1

取消3中的第二个实例,然后......

>>> collection.insert({"c": 3})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/collection.py", line 312, in insert
    continue_on_error, self.__uuid_subtype), safe)
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/connection.py", line 811, in _send_message
    sock = self.__socket()
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/connection.py", line 674, in __socket
    host, port = self.__find_node()
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/connection.py", line 659, in __find_node
    raise AutoReconnect(', '.join(errors))
pymongo.errors.AutoReconnect: could not connect to  localhost:8911: [Errno -5] No address associated with hostname, could not connect to localhost:8911: [Errno 111] Connection refused, could not connect to localhost:8912: [Errno 111] Connection refused, could not connect to  localhost:8912: [Errno -5] No address associated with hostname, localhost:8910 is not primary or master
>>> 
>>> 
>>> collection.insert({"c": 3})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/collection.py", line 312, in insert
    continue_on_error, self.__uuid_subtype), safe)
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/connection.py", line 811, in _send_message
    sock = self.__socket()
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/connection.py", line 674, in __socket
    host, port = self.__find_node()
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/connection.py", line 659, in __find_node
    raise AutoReconnect(', '.join(errors))
pymongo.errors.AutoReconnect: could not connect to  localhost:8911: [Errno -5] No address associated with hostname, could not connect to localhost:8911: [Errno 111] Connection refused, could not connect to localhost:8912: [Errno 111] Connection refused, could not connect to  localhost:8912: [Errno -5] No address associated with hostname, localhost:8910 is not primary or master
>>> 
>>> 
>>> len(list(collection.find()))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/cursor.py", line 703, in next
    if len(self.__data) or self._refresh():
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/cursor.py", line 666, in _refresh
    self.__uuid_subtype))
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/cursor.py", line 616, in __send_message
    **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/connection.py", line 880, in _send_message_with_response
    sock = self.__socket()
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/connection.py", line 674, in __socket
    host, port = self.__find_node()
  File "/usr/local/lib/python2.7/dist-packages/pymongo-2.1.1-py2.7-linux-x86_64.egg/pymongo/connection.py", line 659, in __find_node
    raise AutoReconnect(', '.join(errors))
pymongo.errors.AutoReconnect: could not connect to  localhost:8911: [Errno -5] No 
address associated with hostname, could not connect to localhost:8911: [Errno 111] 
Connection refused, could not connect to localhost:8912: [Errno 111] Connection refused, 
could not connect to  localhost:8912: [Errno -5] No address associated with hostname, 
localhost:8910 is not primary or master
>>> 

mongo(cli)输出

SECONDARY> rs.status()
{
        "set" : "myset",
        "date" : ISODate("2012-02-26T15:09:49Z"),
        "myState" : 2,
        "members" : [
                {
                        "_id" : 0,
                        "name" : "localhost:8910",
                        "health" : 0,
                        "state" : 8,
                        "stateStr" : "(not reachable/healthy)",
                        "uptime" : 0,
                        "optime" : {
                                "t" : 1330268443000,
                                "i" : 1
                        },
                        "optimeDate" : ISODate("2012-02-26T15:00:43Z"),
                        "lastHeartbeat" : ISODate("2012-02-26T15:09:37Z"),
                        "pingMs" : 0,
                        "errmsg" : "socket exception"
                },
                {
                        "_id" : 1,
                        "name" : "localhost:8911",
                        "health" : 1,
                        "state" : 2,
                        "stateStr" : "SECONDARY",
                        "optime" : {
                                "t" : 1330268443000,
                                "i" : 1
                        },
                        "optimeDate" : ISODate("2012-02-26T15:00:43Z"),
                        "self" : true
                },
                {
                        "_id" : 2,
                        "name" : "localhost:8912",
                        "health" : 0,
                        "state" : 8,
                        "stateStr" : "(not reachable/healthy)",
                        "uptime" : 0,
                        "optime" : {
                                "t" : 1330268443000,
                                "i" : 1
                        },
                        "optimeDate" : ISODate("2012-02-26T15:00:43Z"),
                        "lastHeartbeat" : ISODate("2012-02-26T15:09:37Z"),
                        "pingMs" : 0,
                        "errmsg" : "socket exception"
                }
        ],
        "ok" : 1
}
SECONDARY> 
SECONDARY> 
SECONDARY> db.TEST.find().count()
54
SECONDARY> db.TEST.insert({eeee:23232323})
not master
SECONDARY> 
SECONDARY> db.TEST.find().count()
54

2 个答案:

答案 0 :(得分:4)

要解决此问题有两个因素,ReplicaSetConnectionReadPreference.SECONDARY

ReplicaSetConnection("localhost:8910,localhost:8911,localhost8912",  
      replicaSet='myset', read_prefererence=ReadPreference.SECONDARY) 

答案 1 :(得分:1)

使用最新的PyMongo并实例化ReplicaSetConnection而不是Connection。使用ReadPreference将读取指向主要或次要;可以在ReplicaSetConnection中设置首选项,也可以在每个查询中重写:

http://api.mongodb.org/python/current/api/pymongo/index.html#pymongo.ReadPreference