[CP][Bugfix][OBKV]fix session pool hold too much memory when login frequently

This commit is contained in:
obdev 2024-02-09 14:02:09 +00:00 committed by ob-robot
parent 68d387893f
commit b7b06563ac
3 changed files with 23 additions and 13 deletions

View File

@ -33,7 +33,7 @@ int ObTableApiSessPoolMgr::mtl_init(ObTableApiSessPoolMgr *&mgr)
/*
start tableapi retired session task
- 60 second interval
- 5 second interval
- repeated
*/
int ObTableApiSessPoolMgr::start()
@ -45,7 +45,7 @@ int ObTableApiSessPoolMgr::start()
LOG_WARN("table api session pool mgr isn't inited", K(ret));
} else if (OB_FAIL(TG_SCHEDULE(MTL(omt::ObSharedTimer*)->get_tg_id(),
elimination_task_,
ELIMINATE_SESSION_DELAY/* 60s */,
ELIMINATE_SESSION_DELAY/* 5s */,
true/* repeat */))) {
LOG_WARN("failed to schedule tableapi retired session task", K(ret));
} else {
@ -377,7 +377,7 @@ int ObTableApiSessPool::move_node_to_retired_list(ObTableApiSessNode *node)
1. remove session val in free_list.
2. remove session node from retired_nodes_ when node is empty.
3. free node memory.
4. delete 1000 session nodes per times
4. delete 2000 session nodes per times
*/
int ObTableApiSessPool::evict_retired_sess()
{
@ -387,7 +387,7 @@ int ObTableApiSessPool::evict_retired_sess()
ObLockGuard<ObSpinLock> guard(retired_nodes_lock_); // lock retired_nodes_
DLIST_FOREACH_REMOVESAFE_X(node, retired_nodes_, delete_count < BACKCROUND_TASK_DELETE_SESS_NUM) {
if (cur_time - node->get_last_active_ts() < SESS_RETIRE_TIME) {
if (cur_time - node->get_last_active_ts() < SESS_UPDATE_TIME_INTERVAL) {
// do nothing, this node maybe is from ObTableApiSessNodeReplaceOp, some threads maybe is using it.
// we remove it next retire task.
} else if (OB_FAIL(node->remove_unused_sess())) {
@ -545,23 +545,31 @@ int ObTableApiSessPool::create_and_add_node_safe(ObTableApiCredential &credentia
/*
1. only call in login
2. move old to retired list when node exist, create new node otherwise.
3. if the update interval is less than 5 seconds, ignore this update.
*/
int ObTableApiSessPool::update_sess(ObTableApiCredential &credential)
{
int ret = OB_SUCCESS;
ObTableApiSessNode *node = nullptr;
const uint64_t key = credential.hash_val_;
int64_t cur_time = ObTimeUtility::current_time();
if (OB_FAIL(get_sess_node(key, node))) {
if (OB_HASH_NOT_EXIST == ret) { // not exist, create
if (OB_FAIL(create_and_add_node_safe(credential))) {
LOG_WARN("fail to create and add node", K(ret), K(credential));
} else {
ATOMIC_STORE(&last_update_ts_, cur_time);
}
} else {
LOG_WARN("fail to get session node", K(ret), K(key));
}
} else if (cur_time - last_update_ts_ < SESS_UPDATE_TIME_INTERVAL) {
// if the update interval is less than 5 seconds, ignore this update.
} else if (OB_FAIL(replace_sess_node_safe(credential))) { // exist, create and replace old node
LOG_WARN("fail to replace session node", K(ret), K(credential));
} else {
ATOMIC_STORE(&last_update_ts_, cur_time);
}
return ret;

View File

@ -70,7 +70,7 @@ private:
int create_session_pool_safe();
int create_session_pool_unsafe();
private:
static const int64_t ELIMINATE_SESSION_DELAY = 60 * 1000 * 1000; // 60s
static const int64_t ELIMINATE_SESSION_DELAY = 5 * 1000 * 1000; // 5s
bool is_inited_;
common::ObArenaAllocator allocator_;
ObTableApiSessPool *pool_;
@ -87,13 +87,15 @@ class ObTableApiSessPool final
public:
// key is ObTableApiCredential.hash_val_
typedef common::hash::ObHashMap<uint64_t, ObTableApiSessNode*> CacheKeyNodeMap;
static const int64_t SESS_POOL_DEFAULT_BUCKET_NUM = 10; // 取决于客户端登录的用户数量
static const int64_t SESS_RETIRE_TIME = 300 * 1000000; // 超过300s未被访问的session会被标记淘汰
static const int64_t BACKCROUND_TASK_DELETE_SESS_NUM = 1000; // 后台任务每次删除淘汰的session node数量
static const int64_t SESS_POOL_DEFAULT_BUCKET_NUM = 10; // default user number
static const int64_t SESS_RETIRE_TIME = 300 * 1000 * 1000; // marked as retired more than 300 seconds are not accessed
static const int64_t BACKCROUND_TASK_DELETE_SESS_NUM = 2000; // number of eliminated session nodes in background task per time
static const int64_t SESS_UPDATE_TIME_INTERVAL = 5 * 1000 * 1000; // the update interval cannot exceed 5 seconds
public:
explicit ObTableApiSessPool()
: allocator_("TbSessPool", OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()),
is_inited_(false)
is_inited_(false),
last_update_ts_(0)
{}
~ObTableApiSessPool() { destroy(); };
TO_STRING_KV(K_(is_inited),
@ -120,6 +122,7 @@ private:
// 前台login时、后台淘汰时都会操作retired_nodes_,因此需要加锁
common::ObDList<ObTableApiSessNode> retired_nodes_;
ObSpinLock retired_nodes_lock_; // for lock retired_nodes_
int64_t last_update_ts_;
private:
DISALLOW_COPY_AND_ASSIGN(ObTableApiSessPool);
};

View File

@ -170,8 +170,7 @@ TEST_F(TestTableSessPool, mgr_update_session)
ASSERT_NE(nullptr, mgr->pool_);
ASSERT_TRUE(mgr->pool_->is_inited_);
ASSERT_EQ(1, mgr->pool_->key_node_map_.size());
ASSERT_EQ(1, mgr->pool_->retired_nodes_.size_);
ASSERT_EQ(node, mgr->pool_->retired_nodes_.get_last());
ASSERT_EQ(0, mgr->pool_->retired_nodes_.size_);
ASSERT_EQ(OB_SUCCESS, mgr->pool_->get_sess_node(new_cred->hash_val_, node));
ASSERT_NE(nullptr, node);
ASSERT_TRUE(node->sess_lists_.free_list_.is_empty());
@ -184,7 +183,7 @@ TEST_F(TestTableSessPool, mgr_update_session)
ASSERT_NE(nullptr, mgr->pool_);
ASSERT_TRUE(mgr->pool_->is_inited_);
ASSERT_EQ(2, mgr->pool_->key_node_map_.size());
ASSERT_EQ(1, mgr->pool_->retired_nodes_.size_);
ASSERT_EQ(0, mgr->pool_->retired_nodes_.size_);
ASSERT_EQ(OB_SUCCESS, mgr->pool_->get_sess_node(new_cred->hash_val_, node));
ASSERT_NE(nullptr, node);
ASSERT_TRUE(node->sess_lists_.free_list_.is_empty());