文档首页/ 文档数据库服务 DDS/ 常见问题/ 产品咨询/ 什么是逻辑会话(Logical Sessions)
更新时间:2024-09-11 GMT+08:00

什么是逻辑会话(Logical Sessions)

概述

在dds中,服务端会话(server sessions)或者逻辑会话(logical sessions)是一种机制,用于在服务端维护和管理客户端的操作状态。应用程序使用客户端会话与服务端会话进行交互。

会话的生命周期

  1. 会话的创建
    • 会话的显式创建

      会话在客户端请求时由服务端创建。会话通常由驱动程序通过API创建。例如,使用mongo shell创建session:

      // Start a session.
      session = db.getMongo().startSession( { readPreference: { mode: "primary" } } );

      创建的会话将在服务端维护一个独特的会话ID,用于识别和管理会话。

      session { "id" : UUID("1c6480a3-8e8d-4726-9f1b-6bf2f6b2b606") }
    • 会话的隐式创建

      隐式会话是指在执行某些操作时,驱动程序自动创建会话而无需显式地调用startSession方法。隐式会话主要用于简化开发者的代码,使操作更加便捷。当客户执行数据库操作而没有显式地提供会话参数时,驱动程序会自动创建一个会话。例如,在插入文档或查询数据时,驱动程序会在后台创建一个隐式会话,并在操作完成后自动结束会话。

      服务端可以缓存的最大会话数默认为1000000,当会话数大于该值时,将无法显式或者隐式创建会话。

      会话达到上限时的行为

      • 拒绝新的会话:如果会话资源达到上限,DDS将无法创建新的会话。这意味着新的操作请求将会被拒绝或阻塞,直到现有的会话释放资源。
      • 资源争用:大量的会话可能会导致资源争用,例如内存和CPU利用率增加。这可能会影响数据库的性能和响应时间。
      • 事务失败:如果在会话达到上限时尝试启动新事务,可能会导致事务失败。客户端会收到错误消息,指示会话资源已耗尽。
    • 会话的使用

      会话在使用过程中可以进行多种数据库操作,包括读写操作和事务操作。所有在会话上下文中的操作都会绑定到该会话。例如:

      coll1 = session.getDatabase("mydb1").foo;
      coll2 = session.getDatabase("mydb2").bar;
      coll1.insertOne( { abc: 1 } );
      coll2.insertOne( { xyz: 999 } )。
    • 会话的终止

      会话可以显式终止,也可以在超时后自动终止。显式终止通过调用endSession方法:

      session.endSession();

      服务器会自动清理终止会话所占用的资源。

  2. 会话的管理
    • 事务管理

      会话是事务管理的核心。在事务开始时,服务器会在会话上下文中记录事务操作,确保这些操作要么全部提交,要么全部回滚。例如:

      db.getSiblingDB("mydb1").foo.insertOne(
      {abc: 0},
      { writeConcern: { w: "majority", wtimeout: 2000 } }
      )
      db.getSiblingDB("mydb2").bar.insertOne(
      {xyz: 0},
      { writeConcern: { w: "majority", wtimeout: 2000 } }
      )
      // Start a session.
      session = db.getMongo().startSession( { readPreference: { mode: "primary" } } );
      coll1 = session.getDatabase("mydb1").foo;
      coll2 = session.getDatabase("mydb2").bar;
      // Start a transaction
      session.startTransaction( { readConcern: { level: "local" }, writeConcern: { w: "majority" } } );
      // Operations inside the transaction
      try {
      coll1.insertOne( { abc: 1 } );
      coll2.insertOne( { xyz: 999 } );
      } catch (error) {
      // Abort transaction on error
      session.abortTransaction();
      throw error;
      }
      // Commit the transaction using write concern set at transaction start
      session.commitTransaction();
      session.endSession();
    • 会话超时

      会话有默认的超时时间,默认超时时间为30分钟。服务器会在超时后自动终止未活动的会话,以释放资源。

逻辑会话的实现细节

  1. 会话ID

    每个会话都有一个唯一的会话ID,该ID在会话的整个生命周期中保持不变。会话ID用于跟踪和管理会话内的操作。

  2. 会话资源管理

    服务端根据会话的活动情况动态分配资源。未使用的会话元数据会被自动清理,会话元数据清理的writeConcern是majority,这意味着如果majority个数的备机都有时延,则无法清理会话残留的元数据,即使会话结束,服务端的会话元数据也会累积,并且占用会话数量。对于长时间运行的会话,服务端会定期检查其状态,确保不会占用过多资源。

使用最佳实践

  1. 指定w=majority:建议客户在连接DDS实例时指定w=majority,防止主备时延大导致隐式会话累积残留,此外,如果没有以w=majority写入数据,则发生主备倒换时,未同步到备机的数据有丢失风险。
  2. 显式结束会话:尽量在操作完成后显式调用endSession,以释放资源。
  3. 事务内操作尽量少:在事务内执行的操作应尽量少且简洁,以减少锁定和资源占用。