会话
MongoDB Server 3.6 版本引入了客户端逻辑会话的概念。会话是一个抽象概念,表示应用程序执行的以某种方式相关的一组顺序操作。 可以通过 Mongo::Client
创建会话对象,并将其传递给应在该会话上下文中执行的操作方法。
请注意,会话对象不是线程安全的。 它们一次只能由一个线程使用。
创建会话 Mongo::Client
可以通过在客户端上调用start_session
方法并向其传递一个区块来创建会话:
client.start_session do |session| # work with the session end
使用区块形式时,区块完成执行后,驱动程序将自动结束会话。
在不设置选项的情况下调用start_session
是有效的。 这将导致会话对该会话上下文中执行的操作没有影响,除了在发送到服务器的命令中包含会话 ID 之外。 请参阅 API Docs 以了解所有支持的会话选项。
如果驱动程序连接到不支持会话的部署并且调用了start_session
方法,则会引发错误。
请注意,如果在一段时间内未使用,服务器会话将在服务器端被丢弃。 请注意,如果应用程序在客户端上调用#start_session
并等待超过 1 分钟才能使用会话,则由于会话在使用前就会过时,应用程序可能会出现错误。
使用会话
可以将会话对象传递给大多数驱动程序方法,以便可以在该会话的上下文中执行操作。 请参阅 API Docs,了解哪些方法支持会话参数。
创建一个会话并执行插入,然后使用该会话执行查找:
client.start_session do |session| client[:artists].insert_one({ :name => 'FKA Twigs' }, session: session) client[:artists].find({ :name => 'FKA Twigs' }, limit: 1, session: session).first end
如果您想在特定会话的上下文中调用Mongo::Collection::View
上的方法,则可以使用该会话创建Mongo::Collection::View
,然后调用其上的方法:
client.start_session(causal_consistency: true) do |session| view = client[:artists].find({ :name => 'FKA Twigs' }, session: session) view.count # will use the session end
您还可以直接将会话选项传递给这些方法。 此会话将覆盖与Mongo::Collection::View
关联的任何会话:
client.start_session do |session| client.start_session do |second_session| view = client[:artists].find({ :name => 'FKA Twigs' }, session: session) view.count(session: second_session) # will use the second_session end end
创建会话的替代方法
可以通过在客户端上调用start_session
方法来创建会话:
session = client.start_session
当使用start_session
而不向其传递区块时,驾驶员不会自动清理会话,这可能会导致服务器上出现会话累积。 使用 end_session手动结束创建的会话。 超时后,服务器将自动清理旧会话,但应用程序应在不再需要会话时结束会话。
未确认的写入
仅允许在会话机制之外进行未确认的写入;如果为未确认的写入提供了显式会话,则驱动程序不会随该操作一起发送会话 ID。 同样,驱动程序不会将隐式会话用于未确认的写入。
因果一致性(Causal Consistency)
因果一致的会话将允许您读取自己的写入,并保证从节点的读取单调增加。 要创建因果一致会话,请将causal_consistency
选项设置为 true:
session = client.start_session(causal_consistency: true) # The update message goes to the primary. collection = client[:artists] collection.update_one({ '_id' => 1 }, { '$set' => { 'x' => 0 } }, session: session) # Read your write, even when reading from a secondary! collection.find({ '_id' => 1 }, session: session).first # This query returns data at least as new as the previous query, # even if it chooses a different secondary. collection.find({ '_id' => 2 }, session: session).first
由于未确认的写入不会收到服务器的响应(或不等待响应),因此驱动程序无法追踪未确认的写入在逻辑时间中的位置。因此,因果一致的读取与未确认的写入不一致。
请注意,如果您将 causal_consistency 选项设置为 nil(如(causal_consistency: nil)
中所示),它将被解释为 false。
结束会话
要结束会话,请调用end_session
方法:
session.end_session
然后,Ruby 驱动程序会将相应服务器会话的 ID 添加到池中以供重复使用。 当客户端关闭时,驱动程序将向服务器发送命令,结束在服务器会话池中缓存的所有会话。 当客户端关闭时,您可能会在日志中看到此命令。
请注意,使用start_session
的区块语法时,会话会在区块执行完毕后自动结束。