[CP] [BUG.FIX] Add _temporary_file_meta_memory_limit for tmp file

This commit is contained in:
Tyshawn 2024-02-06 15:57:38 +00:00 committed by ob-robot
parent 92ca4c4f9b
commit 971e3746ca
5 changed files with 57 additions and 33 deletions

View File

@ -431,6 +431,11 @@ DEF_INT(_temporary_file_io_area_size, OB_TENANT_PARAMETER, "1", "[0, 50)",
"memory buffer size of temporary file, as a percentage of total tenant memory. "
"Range: [0, 50), percentage",
ObParameterAttr(Section::TENANT, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE));
DEF_INT(_temporary_file_meta_memory_limit_percentage, OB_TENANT_PARAMETER, "0", "[0,100]",
"The memory limit of temporary file meta, and the value is a percentage of the tenant's memory. "
"The default value is 70. For compatibility, 0 is 70% of tenant memory."
"Range: [0, 100], percentage",
ObParameterAttr(Section::TENANT, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE));
DEF_INT(_storage_meta_memory_limit_percentage, OB_TENANT_PARAMETER, "20", "[0, 50)",
"maximum memory for storage meta, as a percentage of total tenant memory. "
"Range: [0, 50), percentage, 0 means no limit to storage meta memory",

View File

@ -1525,25 +1525,12 @@ int ObTmpTenantMemBlockManager::exec_wait()
int ObTmpTenantMemBlockManager::change_mem()
{
int ret = OB_SUCCESS;
uint64_t mem_limit = 0;
omt::ObTenantConfigGuard tenant_config(TENANT_CONF(tenant_id_));
if (!tenant_config.is_valid()) {
COMMON_LOG(INFO, "failed to get tenant config", K_(tenant_id));
} else {
// Here, this memory is used to store temporary file block metadata, which is related to the
// datafile size. So, we set the upper limit of memory to be 70% of tenant memory to
// avoid excessive tenant memory, and affecting system stability. In theory, the limit
// will be reached only when the tenant's memory is extremely small and the disk is extremely
// large.
if (0 == tenant_config->_temporary_file_io_area_size) {
mem_limit = 2 * (2 << 20);
} else {
mem_limit = common::upper_align(
lib::get_tenant_memory_limit(tenant_id_) * 0.7, ObTmpFileStore::get_block_size());
}
allocator_->set_total_limit(mem_limit);
}
// Here, this memory is used to store temporary file block metadata, which is related to the
// datafile size. So, we set the upper limit of memory to be percentage (default, 70%) of tenant memory to
// avoid excessive tenant memory, and affecting system stability. In theory, the limit
// will be reached only when the tenant's memory is extremely small and the disk is extremely
// large.
tenant_store_.refresh_memory_limit(tenant_id_);
return ret;
}

View File

@ -13,6 +13,7 @@
#include "ob_tmp_file_store.h"
#include "ob_tmp_file.h"
#include "share/ob_task_define.h"
#include "observer/omt/ob_tenant_config_mgr.h"
using namespace oceanbase::share;
@ -902,7 +903,9 @@ ObTmpTenantFileStore::ObTmpTenantFileStore()
allocator_(),
io_allocator_(),
tmp_block_manager_(),
tmp_mem_block_manager_(*this)
tmp_mem_block_manager_(*this),
last_access_tenant_config_ts_(0),
last_meta_mem_limit_(TOTAL_LIMIT)
{
}
@ -956,20 +959,41 @@ int ObTmpTenantFileStore::init(const uint64_t tenant_id)
return ret;
}
int64_t ObTmpTenantFileStore::get_memory_limit(const uint64_t tenant_id) const {
int64_t memory_limit = 0;
const int64_t lower_limit = 1 << 30; // 1G memory for 500G disk
const int64_t upper_limit = int64_t(200) * (1 << 30); // 200G memory for 100T disk
const int64_t tenant_memory_limit = lib::get_tenant_memory_limit(tenant_id) * 0.7;
if (tenant_memory_limit < lower_limit) {
memory_limit = lower_limit;
} else if (tenant_memory_limit > upper_limit) {
memory_limit = upper_limit;
} else {
memory_limit = tenant_memory_limit;
void ObTmpTenantFileStore::refresh_memory_limit(const uint64_t tenant_id)
{
const int64_t old_limit = ATOMIC_LOAD(&last_meta_mem_limit_);
const int64_t new_limit = get_memory_limit(tenant_id);
if (old_limit != new_limit) {
allocator_.set_total_limit(new_limit);
ObTaskController::get().allow_next_syslog();
STORAGE_LOG(INFO, "succeed to refresh temporary file meta memory limit", K(tenant_id), K(old_limit), K(new_limit));
}
memory_limit = common::upper_align(memory_limit, ObTmpFileStore::get_block_size());
}
int64_t ObTmpTenantFileStore::get_memory_limit(const uint64_t tenant_id)
{
const int64_t last_access_ts = ATOMIC_LOAD(&last_access_tenant_config_ts_);
int64_t memory_limit = TOTAL_LIMIT;
if (last_access_ts > 0 && common::ObClockGenerator::getClock() - last_access_ts < REFRESH_CONFIG_INTERVAL) {
memory_limit = ATOMIC_LOAD(&last_meta_mem_limit_);
} else {
omt::ObTenantConfigGuard config(TENANT_CONF(tenant_id));
const int64_t tenant_mem_limit = lib::get_tenant_memory_limit(tenant_id);
if (!config.is_valid() || 0 == tenant_mem_limit || INT64_MAX == tenant_mem_limit) {
COMMON_LOG(INFO, "failed to get tenant config", K(tenant_id), K(tenant_mem_limit));
} else {
const int64_t limit_percentage_config = config->_temporary_file_meta_memory_limit_percentage;
const int64_t limit_percentage = 0 == limit_percentage_config ? 70 : limit_percentage_config;
memory_limit = tenant_mem_limit * limit_percentage / 100;
if (OB_UNLIKELY(memory_limit <= 0)) {
STORAGE_LOG(INFO, "memory limit isn't more than 0", K(memory_limit));
memory_limit = ATOMIC_LOAD(&last_meta_mem_limit_);
} else {
ATOMIC_STORE(&last_meta_mem_limit_, memory_limit);
ATOMIC_STORE(&last_access_tenant_config_ts_, common::ObClockGenerator::getClock());
}
}
}
return memory_limit;
}
@ -982,6 +1006,8 @@ void ObTmpTenantFileStore::destroy()
}
allocator_.destroy();
io_allocator_.reset();
last_access_tenant_config_ts_ = 0;
last_meta_mem_limit_ = TOTAL_LIMIT;
is_inited_ = false;
STORAGE_LOG(INFO, "cache num when destroy",
K(ATOMIC_LOAD(&page_cache_num_)), K(ATOMIC_LOAD(&block_cache_num_)));

View File

@ -250,6 +250,7 @@ public:
int read(ObTmpBlockIOInfo &io_info, ObTmpFileIOHandle &handle);
int write(const ObTmpBlockIOInfo &io_info);
int wash_block(const int64_t block_id, ObTmpTenantMemBlockManager::ObIOWaitInfoHandle &handle);
void refresh_memory_limit(const uint64_t tenant_id);
int sync_block(const int64_t block_id, ObTmpTenantMemBlockManager::ObIOWaitInfoHandle &handle);
int wait_write_finish(const int64_t block_id, const int64_t timeout_ms);
int get_disk_macro_block_list(common::ObIArray<MacroBlockId> &macro_id_list);
@ -278,12 +279,14 @@ private:
int free_extent(const int64_t block_id, const int32_t start_page_id, const int32_t page_nums);
int free_macro_block(ObTmpMacroBlock *&t_mblk);
int alloc_macro_block(const int64_t dir_id, const uint64_t tenant_id, ObTmpMacroBlock *&t_mblk);
int64_t get_memory_limit(const uint64_t tenant_id) const;
int64_t get_memory_limit(const uint64_t tenant_id);
int wait_write_io_finish_if_need();
private:
static const uint64_t IO_LIMIT = 4 * 1024L * 1024L * 1024L;
static const uint64_t TOTAL_LIMIT = 15 * 1024L * 1024L * 1024L;
static const uint64_t HOLD_LIMIT = 8 * 1024L * 1024L;
static const uint64_t REFRESH_CONFIG_INTERVAL = 5 * 60 * 1000 * 1000L; // 5min
static const uint64_t BLOCK_SIZE = common::OB_MALLOC_MIDDLE_BLOCK_SIZE;
static constexpr double DEFAULT_PAGE_IO_MERGE_RATIO = 0.5;
@ -297,6 +300,8 @@ private:
common::ObFIFOAllocator io_allocator_;
ObTmpTenantMacroBlockManager tmp_block_manager_;
ObTmpTenantMemBlockManager tmp_mem_block_manager_;
int64_t last_access_tenant_config_ts_;
int64_t last_meta_mem_limit_;
DISALLOW_COPY_AND_ASSIGN(ObTmpTenantFileStore);
};

View File

@ -395,6 +395,7 @@ _storage_leak_check_mod
_storage_meta_memory_limit_percentage
_system_tenant_limit_mode
_temporary_file_io_area_size
_temporary_file_meta_memory_limit_percentage
_trace_control_info
_transfer_finish_trans_timeout
_transfer_process_lock_tx_timeout