会话
MongoDB 服务器 3.6 版本引入了客户端逻辑会话的概念。会话是一个抽象的概念,表示一组以某种方式相关的应用程序的连续操作。可以通过Mongo::Client
创建会话对象,并将其传递给应在该会话上下文中执行的运算方法。
请注意,会话对象不是线程安全的。它们必须一次只能由一个线程使用。
从 Mongo::Client
创建会话
可以通过在客户端调用 start_session
方法并传入一个块来创建会话。
client.start_session do |session| # work with the session end
使用块形式时,驱动程序将在块执行完毕后自动结束会话。
调用 start_session
方法而不设置任何选项是有效的。这将导致创建一个会话,它不会影响该会话上下文中执行的操作,除了在发送到服务器的命令中包含会话 ID。请参阅 API 文档了解所有支持的会话选项。
如果驱动程序连接到不支持会话的部署并调用 start_session
方法,则会抛出错误。
请注意,如果服务器会话在一段时间内未使用,则服务器端会丢弃会话。请注意,如果应用程序在客户端上调用 #start_session
并等待超过 1 分钟才使用会话,则在使用会话之前会话可能会过时,从而导致错误。
使用会话
会话对象可以传递给大多数驱动程序方法,以便在会话的上下文中执行操作。请参阅 API 文档了解哪些方法支持会话参数。
创建会话,并使用该会话执行插入操作,然后使用该会话执行查找操作
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
选项设置为 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
时,在块执行完成后会话将自动结束。