Back to Oceanbase

功能介绍

src/sql/session/ObSQLSessionMgr实现思路.md

latest4.6 KB
Original Source

功能介绍

ObSQLSessionMgr是Observer中用来管理Session的模块,其功能主要分为两块:ObSQLSessionInfo内存的管理和sessid的管理。

ObSQLSessionInfo内存管理

ObSQLSessionMgr负责并发情况下ObSQLSessionInfo的创建、获取和销毁。

Session ID管理

ObSQLSessionMgr负责为每一个连接分配session id,并保证sessid的全局唯一;其次,在observer同obproxy共同部署时,ObSQLSessionMgr需要满足ObProxy Saved Login的需求。

配合proxy进行session和sessid的管理

ObProxy saved_login机制

对于client、ObProxy、ObServer之间有一个约定:如果在client连接ObProxy以后,在连接不断开的情况下,ObProxy与ObServer的所有连接均采用相同的sessid。例如:在ObProxy客户端部署的情况下,ObProxy第一次连接ObServer_1,ObServer_1为其分配sessid_1;此后ObProxy在连接其他ObServer时,均采用sessid_1进行登录。

为了实现 saved_login的,observer采用了switch_sessid的机制;在处理connect请求时,Observer如果发现是proxy的请求,则将当前分配的sessid转换为proxy请求包里面的sessid;该sessid就作为当前连接的唯一标识。

实现思路

ObSQLSessionInfo内存管理

ObSQLSessionMgr采用ObConcurrentHashMapDoNotUseWithHazardValue<Key, Value *> 并发数据结构来管理ObSQLSessionInfo的创建、查询和销毁。ObSQLSessionMgr主要提供create_session/get_session/rever_session/free_session接口。

  • 通过create_session接口创建新的ObSQLSessionInfo,同时会给该ObSQLSessionInfo增加引用计数;
  • 通过get_session接口获取已经创建的ObSQLSessionInfo,同时会给该ObSQLSessionInfo增加引用计数;
  • 通过free_session接口释放ObSQLSessionInfo的内存;调用free_session后会检查该ObSQLSessionInfo的引用计数,如果为0则物理上删除该ObSQLSessionInfo所占有的内存,否则仅在逻辑上删除该ObSQLSessionInfo;
  • 通过revert_session接口,减少相应ObSQLSessionInfo的引用计数。

Session ID 管理

对于session id有如下三个基本概念:sessid, sessid_seq, session_key.

sessid

sessid是session的唯一标识符,为了兼容mysql采用uint32_t表示;同时为了满足sessid的集群全局唯一,32位采用如下方式进行划分:

  • 第0~15位:sessid_seq,observer为每个新建立的连接递增分配的16位id
  • 第16~30位:为server_id,observer启动后会接受到RS为其分配的server_id,将其存放到32位的全局sessid中,用来保证sessid集群全局唯一。注:在启动的短暂时间内,observer并没有接收到RS为其分配的server_id,此时server_id为0,这种情况仅允许tenant_name为空的租户(当前等同于系统租户)登陆,其他情况新到来的连接会返回OB_SERVER_IS_INITING的错误。
  • 第31位:用来区分是observer还是obproxy生成的sessid,其中1表示observer生成的sessid,0表示obproxy生成的sessid。注:ObProxy在客户端部署的情况下,采用ObServer为其分配的sessid进行saved_login;ObProxy在集中部署的情况下,采用自己分配的sessid进行saved_login。

sessid_seq

observer采用16位递增id表示当前server分配的sessid_seq。分配策略如下:

  • ObServer reboot后,sessid_seq从0开始分配,随着连接的到来逐渐递增,如果增加到2^16 - 1,下一次则继续从0开始分配;
  • ObServer restart后,local_sessid的初始值需要从__all_server表中的first_sessid列中读取;注:为了处理ObProxy Saved_login的情况;
  • 在local_sessid递增的过程中,会更新__all_server中的first_sessid列,使得ObServer restart后能够从上次分配的id值继续分配;
  • ObSQLSessionMgr中通过ObConcurrentBitset来存储已经被分配出去的sessid_seq ,每次分配sessid_seq时会查询该bitset,如果sessid_seq已经分配,则id继续递增;

session_key

为了解决ObServer在接收客户端断连接请求后,未能及时释放sessid的问题,引入了session_key的概念;

  • session_key为含有version和sessid两个成员变量的结构体,session_key作为ObSQLSessionInfo在session map中的key;通过session_key对ObSQLSessioInfo进行create_session/get_session/free_session;
  • 当ObServer接收到断连接请求后,在on_disconnect接口中,对sessid 进行unused,并将相应的ObSQLSessionInfo设置为shadow
  • 如果proxy采取saved_login,并使用相同的sessid,observer如果判断出当前full_sessid对应的ObSQLSessionInfo为shadow,则会创建一个新的ObSQLSessionInfo,并指定一个可用的version。