[FEAT MERGE] Implement Resource Throttle

This commit is contained in:
ZenoWang
2023-12-12 15:12:41 +00:00
committed by ob-robot
parent 4235388eaf
commit 56e0ec6dcf
93 changed files with 3353 additions and 1667 deletions

View File

@ -0,0 +1,177 @@
/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#include "ob_mds_allocator.h"
#include "share/allocator/ob_shared_memory_allocator_mgr.h"
#include "share/rc/ob_tenant_base.h"
#include "share/throttle/ob_share_throttle_define.h"
#include "storage/multi_data_source/runtime_utility/mds_tenant_service.h"
#include "storage/tx_storage/ob_tenant_freezer.h"
using namespace oceanbase::storage::mds;
namespace oceanbase {
namespace share {
int64_t ObTenantMdsAllocator::resource_unit_size()
{
static const int64_t MDS_RESOURCE_UNIT_SIZE = OB_MALLOC_NORMAL_BLOCK_SIZE; /* 8KB */
return MDS_RESOURCE_UNIT_SIZE;
}
void ObTenantMdsAllocator::init_throttle_config(int64_t &resource_limit, int64_t &trigger_percentage, int64_t &max_duration)
{
// define some default value
const int64_t MDS_LIMIT_PERCENTAGE = 5;
const int64_t MDS_THROTTLE_TRIGGER_PERCENTAGE = 60;
const int64_t MDS_THROTTLE_MAX_DURATION = 2LL * 60LL * 60LL * 1000LL * 1000LL; // 2 hours
int64_t total_memory = lib::get_tenant_memory_limit(MTL_ID());
// Use tenant config to init throttle config
omt::ObTenantConfigGuard tenant_config(TENANT_CONF(MTL_ID()));
if (tenant_config.is_valid()) {
resource_limit = total_memory * tenant_config->_mds_memory_limit_percentage / 100LL;
trigger_percentage = tenant_config->writing_throttling_trigger_percentage;
max_duration = tenant_config->writing_throttling_maximum_duration;
} else {
SHARE_LOG_RET(WARN, OB_INVALID_CONFIG, "init throttle config with default value");
resource_limit = total_memory * MDS_LIMIT_PERCENTAGE / 100;
trigger_percentage = MDS_THROTTLE_TRIGGER_PERCENTAGE;
max_duration = MDS_THROTTLE_MAX_DURATION;
}
}
void ObTenantMdsAllocator::adaptive_update_limit(const int64_t holding_size,
const int64_t config_specify_resource_limit,
int64_t &resource_limit,
int64_t &last_update_limit_ts,
bool &is_updated)
{
// do nothing
}
int ObTenantMdsAllocator::init()
{
int ret = OB_SUCCESS;
ObMemAttr mem_attr;
// TODO : @gengli new ctx id?
mem_attr.tenant_id_ = MTL_ID();
mem_attr.ctx_id_ = ObCtxIds::MDS_DATA_ID;
mem_attr.label_ = "MdsTable";
ObSharedMemAllocMgr *share_mem_alloc_mgr = MTL(ObSharedMemAllocMgr *);
throttle_tool_ = &(share_mem_alloc_mgr->share_resource_throttle_tool());
MDS_TG(10_ms);
if (IS_INIT){
ret = OB_INIT_TWICE;
SHARE_LOG(WARN, "init tenant mds allocator twice", KR(ret), KPC(this));
} else if (OB_ISNULL(throttle_tool_)) {
ret = OB_ERR_UNEXPECTED;
SHARE_LOG(WARN, "throttle tool is unexpected null", KP(throttle_tool_), KP(share_mem_alloc_mgr));
} else if (MDS_FAIL(allocator_.init(OB_MALLOC_NORMAL_BLOCK_SIZE, block_alloc_, mem_attr))) {
MDS_LOG(WARN, "init vslice allocator failed", K(ret), K(OB_MALLOC_NORMAL_BLOCK_SIZE), KP(this), K(mem_attr));
} else {
allocator_.set_nway(MDS_ALLOC_CONCURRENCY);
is_inited_ = true;
}
return ret;
}
void *ObTenantMdsAllocator::alloc(const int64_t size)
{
int64_t abs_expire_time = THIS_WORKER.get_timeout_ts();
return alloc(size, abs_expire_time);
}
void *ObTenantMdsAllocator::alloc(const int64_t size, const ObMemAttr &attr)
{
UNUSED(attr);
void *obj = alloc(size);
MDS_LOG_RET(WARN, OB_INVALID_ARGUMENT, "VSLICE Allocator not support mark attr", KP(obj), K(size), K(attr));
return obj;
}
void *ObTenantMdsAllocator::alloc(const int64_t size, const int64_t abs_expire_time)
{
bool is_throttled = false;
// try alloc resource from throttle tool
(void)throttle_tool_->alloc_resource<ObTenantMdsAllocator>(size, abs_expire_time, is_throttled);
// if is throttled, do throttle
if (OB_UNLIKELY(is_throttled)) {
if (MTL(ObTenantFreezer *)->exist_ls_freezing()) {
(void)throttle_tool_->skip_throttle<ObTenantTxDataAllocator>(size);
} else {
(void)throttle_tool_->do_throttle<ObTenantTxDataAllocator>(abs_expire_time);
}
}
void *obj = allocator_.alloc(size);
MDS_LOG(DEBUG, "mds alloc ", K(size), KP(obj), K(abs_expire_time));
if (OB_NOT_NULL(obj)) {
MTL(storage::mds::ObTenantMdsService *)
->record_alloc_backtrace(obj,
__thread_mds_tag__,
__thread_mds_alloc_type__,
__thread_mds_alloc_file__,
__thread_mds_alloc_func__,
__thread_mds_alloc_line__); // for debug mem leak
}
return obj;
}
void ObTenantMdsAllocator::free(void *ptr)
{
allocator_.free(ptr);
MTL(storage::mds::ObTenantMdsService *)->erase_alloc_backtrace(ptr);
}
void ObTenantMdsAllocator::set_attr(const ObMemAttr &attr) { allocator_.set_attr(attr); }
void *ObTenantBufferCtxAllocator::alloc(const int64_t size)
{
void *obj = share::mtl_malloc(size, ObMemAttr(MTL_ID(), "MDS_CTX_DEFAULT", ObCtxIds::MDS_CTX_ID));
if (OB_NOT_NULL(obj)) {
MTL(ObTenantMdsService*)->record_alloc_backtrace(obj,
__thread_mds_tag__,
__thread_mds_alloc_type__,
__thread_mds_alloc_file__,
__thread_mds_alloc_func__,
__thread_mds_alloc_line__);// for debug mem leak
}
return obj;
}
void *ObTenantBufferCtxAllocator::alloc(const int64_t size, const ObMemAttr &attr)
{
void *obj = share::mtl_malloc(size, attr);
if (OB_NOT_NULL(obj)) {
MTL(ObTenantMdsService*)->record_alloc_backtrace(obj,
__thread_mds_tag__,
__thread_mds_alloc_type__,
__thread_mds_alloc_file__,
__thread_mds_alloc_func__,
__thread_mds_alloc_line__);// for debug mem leak
}
return obj;
}
void ObTenantBufferCtxAllocator::free(void *ptr)
{
share::mtl_free(ptr);
MTL(ObTenantMdsService*)->erase_alloc_backtrace(ptr);
}
} // namespace share
} // namespace oceanbase