中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

如何做網(wǎng)站微信支付鄭州百度快照優(yōu)化

如何做網(wǎng)站微信支付,鄭州百度快照優(yōu)化,laravel網(wǎng)站怎么做項(xiàng)目,萬(wàn)網(wǎng) 做網(wǎng)站本專題的第一篇文章,配置項(xiàng)的定義及使用方法,詳細(xì)闡述了配置項(xiàng)的基礎(chǔ)用法。對(duì)于那些對(duì)源碼抱有濃厚興趣的同學(xué)來(lái)說(shuō),或許還希望深入了解配置項(xiàng)的實(shí)現(xiàn)原理,甚至渴望親自添加新的配置項(xiàng),以滿足個(gè)性化的功能需求。 本文通…

本專題的第一篇文章,配置項(xiàng)的定義及使用方法,詳細(xì)闡述了配置項(xiàng)的基礎(chǔ)用法。對(duì)于那些對(duì)源碼抱有濃厚興趣的同學(xué)來(lái)說(shuō),或許還希望深入了解配置項(xiàng)的實(shí)現(xiàn)原理,甚至渴望親自添加新的配置項(xiàng),以滿足個(gè)性化的功能需求。

本文通過(guò)剖析“如何新增配置項(xiàng)”這一話題,并結(jié)合配置項(xiàng)源碼的具體實(shí)現(xiàn),來(lái)詳細(xì)講解配置項(xiàng)的定義、初始化、內(nèi)部訪問(wèn)及同步機(jī)制。

如何新增配置項(xiàng)?

要新增一個(gè)配置項(xiàng),首先在 src/share/parameter/ob_parameter_seed.ipp 文件中,按照下面的格式定義配置項(xiàng)。

// 定義一個(gè)集群級(jí)別的、INT類型的配置項(xiàng),動(dòng)態(tài)生效
DEF_INT(cpu_count, OB_CLUSTER_PARAMETER, "0", "[0,]","the number of CPU\\'s in the system. ""If this parameter is set to zero, the number will be set according to sysconf; ""otherwise, this parameter is used. Range: [0,+∞) in integer",ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE));// 定義一個(gè)租戶級(jí)別的、TIME類型的配置項(xiàng),動(dòng)態(tài)生效,并附帶一個(gè)合法性檢查類 ObConfigStaleTimeChecker
DEF_TIME_WITH_CHECKER(max_stale_time_for_weak_consistency, OB_TENANT_PARAMETER, "5s",common::ObConfigStaleTimeChecker,"[5s,)","the max data stale time that cluster weak read version behind current timestamp,""no smaller than weak_read_version_refresh_interval, range: [5s, +∞)",ObParameterAttr(Section::TENANT, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE));

其中每個(gè)參數(shù)的含義如下:

參數(shù)說(shuō)明舉例
配置項(xiàng)宏定義配置的宏,可以選擇附帶合法性檢查函數(shù)DEF_XXX、DEF_XXX_WITH_CHECKER
配置項(xiàng)名配置項(xiàng)的名字一般格式:xxx_xxx_xxx
生效范圍租戶配置項(xiàng) or 集群配置項(xiàng)OB_CLUSTER_PARAMETER、OB_TENANT_PARAMETER
默認(rèn)值默認(rèn)值必須在取值范圍中"0", "True", "100ms", "20GB", "random"
取值范圍布爾類型和字符串類型不需要取值范圍"[0,]", "[0M,]", "[1s, 180s]"
描述介紹該配置項(xiàng)的功能和注意事項(xiàng)"enable xxx"
配置項(xiàng)屬性① Section:所屬模塊;
② Source:來(lái)源;
③ EditLevel:生效方式;
① OBSERVER、TENANT、TRANS
② DEFAULT
③ DYNAMIC_EFFECTIVE、STATIC_EFFECTIVE

DEF_XXX 宏最終展開(kāi)是一個(gè)類的聲明,并同時(shí)定義一個(gè)對(duì)象,對(duì)象名就是配置項(xiàng)名。

比如 DEF_TIME_WITH_CHECKER 宏,最終展開(kāi)是一個(gè) ObConfigTimeItem 類,重載 operator= 操作符讓該類可以像基礎(chǔ)數(shù)據(jù)類型一樣進(jìn)行賦值操作。

#define _DEF_PARAMETER_CHECKER_EASY(access_specifier, param, scope, name, def, checker, args...) \
access_specifier:                                                                          \class ObConfig ## param ## Item ## _ ## name                                 \: public common::ObConfig ## param ## Item                               \{                                                                            \public:                                                                     \ObConfig ## param ## Item ## _ ## name()                                   \: common::ObConfig ## param ## Item(                                   \local_container(), scope, #name, def, args)                        \{                                                                          \add_checker(OB_NEW(checker, g_config_mem_attr));                         \}                                                                          \template <class T>                                                         \ObConfig ## param ## Item ## _ ## name& operator=(T value)                 \{                                                                          \common::ObConfig ## param ## Item::operator=(value);                     \return *this;                                                            \}                                                                          \} name;

ObConfigTimeItemXxx 繼承的是一個(gè) ObConfigIntegralItem 類,所以 time 類型的數(shù)據(jù)本質(zhì)上是一個(gè) int64_t 變量。

class ObConfigTimeItem: public ObConfigIntegralItem
{
public:......static const uint64_t VALUE_BUF_SIZE = 32UL;char value_str_[VALUE_BUF_SIZE];char value_reboot_str_[VALUE_BUF_SIZE];
};

ObConfigIntegralItem 類重載了操作符 operator const int64_t &() const,在代碼中訪問(wèn)該類對(duì)象的對(duì)象名時(shí),實(shí)際上返回的是對(duì)象的 value_值。

class ObConfigIntegralItem: public ObConfigItem
{// get_value() return the real-time valueint64_t get_value() const { return value_; }// get() return the real-time value if it does not need reboot, otherwise it return initial_valueint64_t get() const { return value_; }operator const int64_t &() const { return value_; }private:int64_t value_;

配置項(xiàng)定義完成后,重新編譯部署 OBServer,就可以對(duì)這個(gè)配置項(xiàng)進(jìn)行查詢和修改了。不過(guò)現(xiàn)在這個(gè)配置項(xiàng)沒(méi)有任何功能,還需要在代碼中用起來(lái)才能生效。

配置項(xiàng)初始化

集群配置項(xiàng) ObServerConfig

集群配置項(xiàng)在 OBServer 啟動(dòng)時(shí)進(jìn)行初始化,首先會(huì)從配置項(xiàng)的定義中獲取默認(rèn)值,然后從持久化配置文件中獲取歷史值(非首次啟動(dòng)),最后從 OBServer 的執(zhí)行參數(shù)中獲取最新值。它們的優(yōu)先級(jí)是:執(zhí)行參數(shù) > 持久化配置文件 > 默認(rèn)值。

配置項(xiàng)對(duì)象構(gòu)造

集群配置項(xiàng)定義在 ObServerConfig 類中,通過(guò)在 ObConfigManager 類中定義了一個(gè) ObServerConfig 實(shí)例,當(dāng) OBServer 啟動(dòng)時(shí),它們及其成員變量的構(gòu)造函數(shù)就會(huì)被調(diào)用。

class ObServerConfig : public ObCommonConfig
{
public:friend class ObServerMemoryConfig;int init(const ObSystemConfig &config);static ObServerConfig &get_instance();#undef OB_CLUSTER_PARAMETER
#define OB_CLUSTER_PARAMETER(args...) args
#include "share/parameter/ob_parameter_seed.ipp"
#undef OB_CLUSTER_PARAMETER
}

每個(gè)配置項(xiàng)都有默認(rèn)值,在配置項(xiàng)的構(gòu)造函數(shù)中會(huì)將 value_ 置為默認(rèn)值。

以下是相關(guān)函數(shù)的調(diào)用流程,以及關(guān)鍵函數(shù)的代碼解析。有的函數(shù)只是省略了參數(shù)列表,不代表沒(méi)有參數(shù)。

  • ObConfigTimeItem::ObConfigTimeItem()
  • ObConfigIntegralItem::init()
  • ObConfigItem::init()
  • ObConfigItem::set_value(const char *str)
  • ObConfigIntegralItem::set(const char *str)

其中 str 就是一開(kāi)始定義的配置項(xiàng)默認(rèn)值,將 str 中的字符串轉(zhuǎn)化為對(duì)應(yīng)類型的數(shù)據(jù),然后賦值給 value_。

inline bool ObConfigIntegralItem::set(const char *str)
{bool valid = true;const int64_t value = parse(str, valid);if (valid) {value_ = value;}return valid;
}

配置文件解析

當(dāng)集群配置項(xiàng)都構(gòu)造完成后,再?gòu)某志没呐渲梦募?etc/observer.config.bin 加載配置項(xiàng)。(在 OBServer 初次啟動(dòng)時(shí),配置文件為空,所以不會(huì)執(zhí)行這一步)

  • ObServer::init()
  • ObServer::init_config()
  • ObConfigManager::load_config(const char *path)
  • ObServerConfig::deserialize_with_compat()
  • OB_DEF_DESERIALIZE(ObServerConfig)

先調(diào)用 ObCommonConfig::deserialize() 函數(shù)解析集群配置項(xiàng),再調(diào)用 OTC_MGR.deserialize() 函數(shù)解析租戶配置項(xiàng)。

OB_DEF_DESERIALIZE(ObServerConfig)
{} else if (OB_FAIL(ObCommonConfig::deserialize(buf, data_len, pos))) {LOG_ERROR("deserialize cluster config failed", K(ret));} else if (OB_FAIL(OTC_MGR.deserialize(buf, data_len, pos))){LOG_ERROR("deserialize tenant config failed", K(ret));}
  • OB_DEF_DESERIALIZE(ObCommonConfig)
  • ObCommonConfig::add_extra_config()

將文件中集群配置項(xiàng)的值加載到內(nèi)存數(shù)據(jù)結(jié)構(gòu)中。

int ObCommonConfig::add_extra_config(const char *config_str,int64_t version /* = 0 */ ,bool check_name /* = false */,bool check_unit /* = true */)
{......while (OB_SUCC(ret) && OB_NOT_NULL(token)) {if (strncmp(token, "enable_production_mode=", 23) == 0) {......} else if (OB_ISNULL(pp_item = container_.get(ObConfigStringKey(name)))) {......if (OB_FAIL(ret) || OB_ISNULL(pp_item)) {} else if (check_unit && !(*pp_item)->check_unit(value)) {ret = OB_INVALID_CONFIG;LOG_ERROR("Invalid config value", K(name), K(value), K(ret));} else if (!(*pp_item)->set_value(value)) {ret = OB_INVALID_CONFIG;LOG_ERROR("Invalid config value", K(name), K(value), K(ret));} else if (!(*pp_item)->check()) {ret = OB_INVALID_CONFIG;const char* range = (*pp_item)->range();if (OB_ISNULL(range) || strlen(range) == 0) {LOG_ERROR("Invalid config, value out of range", K(name), K(value), K(ret));} else {_LOG_ERROR("Invalid config, value out of %s (for reference only). name=%s, value=%s, ret=%d", range, name, value, ret);}} else {(*pp_item)->set_version(version);LOG_INFO("Load config succ", K(name), K(value));}

執(zhí)行參數(shù)解析

當(dāng)配置文件中的數(shù)據(jù)加載完成后,再解析 OBServer 執(zhí)行命令中的配置項(xiàng)參數(shù)。

  • ObServer::init_config()

其中 config_.add_extra_config(opts_.optstr_, start_time_) 函數(shù)將參數(shù)解析為配置項(xiàng)的值,然后加載到配置項(xiàng)結(jié)構(gòu)中。最后調(diào)用 dump2file() 函數(shù),將前面解析出來(lái)的配置項(xiàng)全部持久化到"etc/observer.config.bin"文件中。

int ObServer::init_config()
{int ret = OB_SUCCESS;bool has_config_file = true;// set dump pathconst char *dump_path = "etc/observer.config.bin";config_mgr_.set_dump_path(dump_path);if (OB_FILE_NOT_EXIST == (ret = config_mgr_.load_config())) {has_config_file = false;ret = OB_SUCCESS;}......if (opts_.optstr_ && strlen(opts_.optstr_) > 0) {if (OB_FAIL(config_.add_extra_config(opts_.optstr_, start_time_))) {LOG_ERROR("invalid config from cmdline options", K(opts_.optstr_), KR(ret));}}......if (is_arbitration_mode()) {// arbitration mode, dump config params to file directlyif (OB_FAIL(config_mgr_.dump2file())) {LOG_ERROR("config_mgr_ dump2file failed", KR(ret));} else {LOG_INFO("config_mgr_ dump2file success", KR(ret));}

如果是用 OBD 部署集群,OBServer 第一次啟動(dòng)時(shí),命令中會(huì)帶上"xxx.yaml"文件中的啟動(dòng)參數(shù)。例如:

/data/user/observer1/bin/observer -p 23400 -P 23401 -z zone1 -c 1 -d /data/user/observer1/store -i lo -r 127.0.0.1:23401:23400 -o __min_full_resource_pool_memory=268435456,major_freeze_duty_time=Disable,datafile_size=20G,memory_limit=10G,system_memory=5G,cpu_count=24,stack_size=512K,cache_wash_threshold=1G,workers_per_cpu_quota=10,schema_history_expire_time=1d,net_thread_count=4,minor_freeze_times=10,enable_separate_sys_clog=False,enable_merge_by_turn=False,syslog_io_bandwidth_limit=10G,enable_async_syslog=False

集群第一次部署完成之后,"etc/observer.config.bin"文件才會(huì)被創(chuàng)建,之后重啟 OBServer 就可以不帶參數(shù)了,進(jìn)程會(huì)從該文件中讀取修改后的配置項(xiàng)。

租戶配置項(xiàng) ObTenantConfig

創(chuàng)建租戶時(shí)初始化

租戶級(jí)別配置項(xiàng)首先在創(chuàng)建租戶時(shí)進(jìn)行初始化,在代碼中是一個(gè) ObTenantConfig 對(duì)象。

(不只這一條調(diào)用路徑,但最終會(huì)調(diào)用 add_tenant_config() 函數(shù))

  • ObRpcNotifyTenantServerUnitResourceP::process()
  • ObTenantNodeBalancer::notify_create_tenant(oceanbase::obrpc::TenantServerUnitConfig const&)
  • ObTenantNodeBalancer::check_new_tenant(oceanbase::share::ObUnitInfoGetter::ObTenantConfig const&, long)
  • ObMultiTenant::create_tenant(oceanbase::omt::ObTenantMeta const&, bool, long)
  • ObTenantConfigMgr::add_tenant_config(uint64_t tenant_id)

申請(qǐng)一個(gè)新的 ObTenantConfig 對(duì)象,調(diào)用 init() 初始化,然后添加到 config_map_中。

int ObTenantConfigMgr::add_tenant_config(uint64_t tenant_id)
{int ret = OB_SUCCESS;ObTenantConfig *const *config = nullptr;DRWLock::WRLockGuard guard(rwlock_);if (is_virtual_tenant_id(tenant_id)|| OB_NOT_NULL(config = config_map_.get(ObTenantID(tenant_id)))) {if (nullptr != config) {ObTenantConfig *new_config = *config;new_config->set_deleting(false);}} else {ObTenantConfig *new_config = nullptr;new_config = OB_NEW(ObTenantConfig, SET_USE_UNEXPECTED_500("TenantConfig"), tenant_id);if (OB_NOT_NULL(new_config)) {if(OB_FAIL(new_config->init(this))) {LOG_WARN("new tenant config init failed", K(ret));} else if (OB_FAIL(config_map_.set_refactored(ObTenantID(tenant_id),new_config, 0))) {LOG_WARN("add new tenant config failed", K(ret));}......

因?yàn)?ObTenantConfig 引入了租戶配置項(xiàng)的定義,因此在構(gòu)造 ObTenantConfig 對(duì)象時(shí)就完成了配置項(xiàng)的構(gòu)造。

class ObTenantConfig : public ObCommonConfig
{#undef OB_TENANT_PARAMETER
#define OB_TENANT_PARAMETER(args...) args
#include "share/parameter/ob_parameter_seed.ipp"
#undef OB_TENANT_PARAMETER
};

重啟時(shí)初始化

在 OBServer 重新啟動(dòng)時(shí),已有租戶的配置項(xiàng)也會(huì)進(jìn)行初始化。

  • OB_DEF_DESERIALIZE(ObServerConfig)

調(diào)用 OTC_MGR.deserialize() 函數(shù)。

OB_DEF_DESERIALIZE(ObServerConfig)
{} else if (OB_FAIL(ObCommonConfig::deserialize(buf, data_len, pos))) {LOG_ERROR("deserialize cluster config failed", K(ret));} else if (OB_FAIL(OTC_MGR.deserialize(buf, data_len, pos))){LOG_ERROR("deserialize tenant config failed", K(ret));}
  • OB_DEF_DESERIALIZE(ObTenantConfigMgr)

讀取文件中租戶配置項(xiàng),根據(jù) tenant_id 獲取 config,然后將buf中的配置項(xiàng)解析到 config 中。

OB_DEF_DESERIALIZE(ObTenantConfigMgr)
{int ret = OB_SUCCESS;if (data_len == 0 || pos >= data_len) {} else {while(OB_SUCC(ret) && pos < data_len) {......ObTenantConfig *config = nullptr;if (OB_FAIL(config_map_.get_refactored(ObTenantID(tenant_id), config))) {if (ret != OB_HASH_NOT_EXIST || OB_FAIL(add_tenant_config(tenant_id))) {LOG_ERROR("get tenant config failed", K(tenant_id),  K(ret));break;}ret = config_map_.get_refactored(ObTenantID(tenant_id), config);}if (OB_SUCC(ret)) {pos = saved_pos;ret = config->deserialize(buf, data_len, pos);}......

在代碼中查詢配置項(xiàng)

外部查詢

當(dāng)用戶使用"show ..."類型的命令時(shí),OBServer 內(nèi)部有統(tǒng)一的處理函數(shù):ObShowResolver::resolve()。查詢配置項(xiàng)的命令會(huì)被解析為 T_SHOW_PARAMETERS 類型,通過(guò)查詢 __all_virtual_tenant_parameter_stat 表獲取配置項(xiàng)的值。

int ObShowResolver::resolve(const ParseNode &parse_tree)
{......case T_SHOW_PARAMETERS: {......if (params_.show_seed_) {char local_ip[OB_MAX_SERVER_ADDR_SIZE] = "";if (OB_UNLIKELY(true != GCONF.self_addr_.ip_to_string(local_ip, sizeof(local_ip)))) {ret = OB_CONVERT_ERROR;} else {GEN_SQL_STEP_1(ObShowSqlSet::SHOW_PARAMETERS_SEED);GEN_SQL_STEP_2(ObShowSqlSet::SHOW_PARAMETERS_SEED, REAL_NAME(OB_SYS_DATABASE_NAME, OB_ORA_SYS_SCHEMA_NAME), REAL_NAME(OB_ALL_VIRTUAL_TENANT_PARAMETER_STAT_TNAME, OB_ALL_VIRTUAL_TENANT_PARAMETER_STAT_ORA_TNAME),local_ip, GCONF.self_addr_.get_port());}} else if (OB_SYS_TENANT_ID == show_tenant_id) {GEN_SQL_STEP_1(ObShowSqlSet::SHOW_PARAMETERS);GEN_SQL_STEP_2(ObShowSqlSet::SHOW_PARAMETERS,REAL_NAME(OB_SYS_DATABASE_NAME, OB_ORA_SYS_SCHEMA_NAME),REAL_NAME(OB_ALL_VIRTUAL_TENANT_PARAMETER_STAT_TNAME, OB_ALL_VIRTUAL_TENANT_PARAMETER_STAT_ORA_TNAME),show_tenant_id);} else {GEN_SQL_STEP_1(ObShowSqlSet::SHOW_PARAMETERS);GEN_SQL_STEP_2(ObShowSqlSet::SHOW_PARAMETERS,REAL_NAME(OB_SYS_DATABASE_NAME, OB_ORA_SYS_SCHEMA_NAME),REAL_NAME(OB_ALL_VIRTUAL_TENANT_PARAMETER_STAT_TNAME, OB_ALL_VIRTUAL_TENANT_PARAMETER_STAT_ORA_TNAME),show_tenant_id);}
}// 最終查詢的虛擬表為 __all_virtual_tenant_parameter_stat
const char *const OB_ALL_VIRTUAL_TENANT_PARAMETER_STAT_TNAME = "__all_virtual_tenant_parameter_stat";

查詢?cè)撎摂M表需要先初始化一個(gè) ObAllVirtualTenantParameterStat 對(duì)象,然后調(diào)用 inner_open() 函數(shù),再循環(huán)調(diào)用 inner_get_next_row() 函數(shù)遍歷虛擬表。

  • ObVirtualTableIterator::get_next_row(common::ObNewRow*&)
  • ObAllVirtualTenantParameterStat::inner_get_next_row(common::ObNewRow*&)

其中 inner_sys_get_next_row() 函數(shù)獲取集群配置項(xiàng),inner_tenant_get_next_row() 函數(shù)獲取租戶配置項(xiàng),最后根據(jù)查詢條件進(jìn)行篩選,返回滿足條件的配置項(xiàng)。

int ObAllVirtualTenantParameterStat::inner_get_next_row(ObNewRow *&row)
{int ret = OB_SUCCESS;if (OB_UNLIKELY(!inited_)) {ret = OB_NOT_INIT;SERVER_LOG(WARN, "not inited", K(inited_), KR(ret));} else if (show_seed_) {ret = inner_seed_get_next_row(row);} else {if (OB_SUCC(inner_sys_get_next_row(row))) {} else if (OB_ITER_END == ret) {ret = inner_tenant_get_next_row(row);}}return ret;
}
  • ObAllVirtualTenantParameterStat::inner_sys_get_next_row(common::ObNewRow*&)

從 GCONF 中獲取集群配置項(xiàng)。

int ObAllVirtualTenantParameterStat::inner_sys_get_next_row(common::ObNewRow *&row)
{/*cluster parameter does not belong to any tenant*/return fill_row_(row, sys_iter_, GCONF.get_container(), NULL);
}// 集群配置項(xiàng)迭代器也就是 GCONF 中一個(gè) hashmap 的迭代器sys_iter_ = GCONF.get_container().begin();
  • ObAllVirtualTenantParameterStat::inner_tenant_get_next_row(common::ObNewRow *&row)

從 tenant_config_中獲取租戶配置項(xiàng)。

int ObAllVirtualTenantParameterStat::inner_tenant_get_next_row(common::ObNewRow *&row)
{// 租戶配置項(xiàng)迭代器也就是 tenant_config_ 中一個(gè) hashmap 的迭代器if (cur_tenant_idx_ < 0 // first come-in// current tenant is over|| (tenant_config_.is_valid() && tenant_iter_ == tenant_config_->get_container().end())) {// find next valid tenantwhile (OB_SUCC(ret) && ++cur_tenant_idx_ < tenant_id_list_.count()) {uint64_t tenant_id = tenant_id_list_.at(cur_tenant_idx_);tenant_config_.set_config(TENANT_CONF(tenant_id));if (tenant_config_.is_valid()) {tenant_iter_ = tenant_config_->get_container().begin();......}......} else {const uint64_t tenant_id = tenant_id_list_.at(cur_tenant_idx_);if (OB_FAIL(fill_row_(row,tenant_iter_,tenant_config_->get_container(),&tenant_id))) {SERVER_LOG(WARN, "fill row fail", KR(ret), K(tenant_id), K(tenant_config_->get_tenant_id()),K(cur_tenant_idx_), K(tenant_id_list_));}

內(nèi)部獲取

集群配置項(xiàng)

因?yàn)榕渲庙?xiàng)重載了操作符 operator &(),所以集群配置項(xiàng)直接通過(guò) GCONF.xxx 的形式訪問(wèn)即可。

#include "share/config/ob_server_config.h"GCONF.enable_sql_audit 

在代碼中有需要的地方,可以用“if (GCONF.enable_xxx)”來(lái)控制分支的走向,或者用“GCONF.xxx_time”來(lái)進(jìn)行時(shí)間的計(jì)算,這樣就可以把配置項(xiàng)使用起來(lái)了。

租戶配置項(xiàng)

訪問(wèn)租戶配置項(xiàng)需要先調(diào)用 OTC_MGR.read_tenant_config() 函數(shù)獲取租戶的 config,然后從 config 中獲取指定的配置項(xiàng)。以租戶配置項(xiàng) max_stale_time_for_weak_consistency 為例,為其封裝一個(gè)取值函數(shù)。

  • ObWeakReadUtil::max_stale_time_for_weak_consistency(const uint64_t tenant_id, int64_t ignore_warn)

如果獲取租戶 config 成功,則從 config 中獲取配置項(xiàng)的值,否則返回配置項(xiàng)的默認(rèn)值并打印日志。

int64_t ObWeakReadUtil::max_stale_time_for_weak_consistency(const uint64_t tenant_id, int64_t ignore_warn)
{int64_t max_stale_time = 0;OTC_MGR.read_tenant_config(tenant_id,oceanbase::omt::ObTenantConfigMgr::default_fallback_tenant_id(),/* success */ [&max_stale_time](const omt::ObTenantConfig &config) mutable {max_stale_time = config.max_stale_time_for_weak_consistency;},/* failure */ [tenant_id, ignore_warn, &max_stale_time]() mutable {max_stale_time = DEFAULT_MAX_STALE_TIME_FOR_WEAK_CONSISTENCY;if (IGNORE_TENANT_EXIST_WARN != ignore_warn && REACH_TIME_INTERVAL(1 * 1000 * 1000L)) {TRANS_LOG_RET(WARN, OB_ERR_UNEXPECTED, "tenant not exist when get max stale time for weak consistency,"" use default max stale time instead",K(tenant_id), K(max_stale_time), K(lbt()));}});return max_stale_time;
}
  • ObTenantConfigMgr::read_tenant_config()

從 config_map_中獲取 tenant_id 對(duì)應(yīng)的config,成功則調(diào)用 SuccessFunctor,失敗則調(diào)用 FailureFunctor。

int ObTenantConfigMgr::read_tenant_config(const uint64_t tenant_id,const uint64_t fallback_tenant_id,const SuccessFunctor &on_success,const FailureFunctor &on_failure) const
{int ret = OB_SUCCESS;ObTenantConfig *config = nullptr;DRWLock::RDLockGuard guard(rwlock_);if (OB_FAIL(config_map_.get_refactored(ObTenantID(tenant_id), config))) {if (fallback_tenant_id > 0 && OB_INVALID_ID != fallback_tenant_id) {if (OB_FAIL(config_map_.get_refactored(ObTenantID(fallback_tenant_id), config))) {LOG_WARN("failed to get tenant config", K(fallback_tenant_id), K(ret), K(lbt()));}} else {LOG_WARN("failed to get tenant config", K(tenant_id), K(ret));}}if (OB_SUCC(ret) && OB_NOT_NULL(config)) {on_success(*config);} else {on_failure();LOG_WARN("fail read tenant config", K(tenant_id), K(ret));}return ret;
}

在代碼中修改配置項(xiàng)

外部修改

修改集群配置項(xiàng)

系統(tǒng)租戶執(zhí)行修改集群配置項(xiàng)命令時(shí),內(nèi)部會(huì)向 __all_sys_parameter 表中插入一條記錄(該表只記錄增量數(shù)據(jù)),實(shí)際執(zhí)行的是以下sql命令。

select config_version, zone, svr_type, svr_ip, svr_port, name, data_type, value, info, section, scope, source, edit_level from __all_sys_parameter
INSERT INTO __all_sys_parameter (zone, svr_type, svr_ip, svr_port, name, data_type, value, info, config_version, gmt_modified, section, scope, source, edit_level) VALUES ('', 'observer', 'ANY', 0, 'cpu_count', 'varchar', '9', '', 1689734424757370, usec_to_time(1689734424757370), 'OBSERVER', 'CLUSTER', 'DEFAULT', 'DYNAMIC_EFFECTIVE') ON DUPLICATE KEY UPDATE data_type = 'varchar', value = '9', info = '', config_version = 1689734424757370, gmt_modified = usec_to_time(1689734424757370), section = 'OBSERVER', scope = 'CLUSTER', source = 'DEFAULT', edit_level = 'DYNAMIC_EFFECTIVE'
select config_version, zone, svr_type, svr_ip, svr_port, name, data_type, value, info, section, scope, source, edit_level from __all_sys_parameter
select config_version, zone, svr_type, svr_ip, svr_port, name, data_type, value, info, section, scope, source, edit_level from __all_sys_parameter

將修改后的值插入內(nèi)部表之后,修改配置項(xiàng)命令就執(zhí)行完成了。之后內(nèi)部會(huì)將表中的增量數(shù)據(jù)刷新到各節(jié)點(diǎn)的本地?cái)?shù)據(jù)結(jié)構(gòu)中,此時(shí)才算真正完成了集群配置項(xiàng)更新。

修改租戶配置項(xiàng)

執(zhí)行租戶配置項(xiàng)修改命令后,內(nèi)部會(huì)執(zhí)行兩條sql,先往 __tenant_parameter 內(nèi)部表中插入一行數(shù)據(jù)(該表只記錄增量數(shù)據(jù)),然后往 __all_rootservice_event_history 內(nèi)部表中插入一條修改記錄。

INSERT INTO __tenant_parameter (tenant_id, zone, svr_type, svr_ip, svr_port, name, data_type, value, info, config_version, gmt_modified, section, scope, source, edit_level) VALUES (1004, '', 'observer', 'ANY', 0, 'max_stale_time_for_weak_consistency', 'varchar', '7s', '', 1689732907024711, usec_to_time(1689732907024711), 'TENANT', 'TENANT', 'DEFAULT', 'DYNAMIC_EFFECTIVE') ON DUPLICATE KEY UPDATE data_type = 'varchar', value = '7s', info = '', config_version = 1689732907024711, gmt_modified = usec_to_time(1689732907024711), section = 'TENANT', scope = 'TENANT', source = 'DEFAULT', edit_level = 'DYNAMIC_EFFECTIVE'
INSERT INTO __all_rootservice_event_history (gmt_create, module, event, name1, value1, name2, value2, rs_svr_ip, rs_svr_port) VALUES (usec_to_time(1689732907031822), 'root_service', 'admin_set_config', 'ret', 0, 'arg', '{items:[{name:"max_stale_time_for_weak_consistency", value:"7s", comment:"", zone:"", server:"0.0.0.0:0", tenant_name:"", exec_tenant_id:1004, tenant_ids:[1004]}], is_inner:false}', '127.0.0.1', 23401

同樣的,修改內(nèi)部表之后SQL命令就會(huì)返回,之后再由后臺(tái)線程刷新各節(jié)點(diǎn)的租戶配置項(xiàng)。

內(nèi)部更新(同步機(jī)制)

內(nèi)部主動(dòng)更新配置項(xiàng),就是把 __tenant_parameter 和 __all_sys_parameter 內(nèi)部表中的增量配置項(xiàng)同步到本地的過(guò)程。

集群配置項(xiàng)同步
  • ObLeaseStateMgr::start_heartbeat()

后臺(tái)任務(wù) hb_ 每2s執(zhí)行一次。

int ObLeaseStateMgr::start_heartbeat()
{int ret = OB_SUCCESS;if (!inited_) {ret = OB_NOT_INIT;LOG_WARN("not init", K(ret));} else {const bool repeat = false;if (OB_FAIL(hb_timer_.schedule(hb_, DELAY_TIME, repeat))) {LOG_WARN("schedule failed", LITERAL_K(DELAY_TIME), K(repeat), K(ret));}}return ret;
}static const int64_t DELAY_TIME = 2 * 1000 * 1000;//2s
  • ObLeaseStateMgr::HeartBeat::runTimerTask()

......

  • ObHeartBeatProcess::do_heartbeat_event(oceanbase::share::ObLeaseResponse const&)
  • ObHeartBeatProcess::ObZoneLeaseInfoUpdateTask::runTimerTask()

......

  • ObConfigManager::got_version(long, bool)
  • ObConfigManager::UpdateTask::runTimerTask()

該函數(shù)是刷新配置項(xiàng)的后臺(tái)定時(shí)任務(wù),會(huì)調(diào)用 update_local() 函數(shù),將內(nèi)部表中的數(shù)據(jù)同步到本地配置項(xiàng)中。

void ObConfigManager::UpdateTask::runTimerTask()
{......} else if (update_local_) {config_mgr_->current_version_ = version;if (OB_FAIL(config_mgr_->system_config_.clear())) {// just print log, ignore retLOG_WARN("Clear system config map failed", K(ret));} else {// do nothing}if (OB_FAIL(config_mgr_->update_local(version))) {LOG_WARN("Update local config failed", K(ret));// recovery current_version_config_mgr_->current_version_ = old_current_version;// retry update local config in 1s laterif (OB_FAIL(TG_SCHEDULE(lib::TGDefIDs::CONFIG_MGR, *this, 1000 * 1000L, false))) {LOG_WARN("Reschedule update local config failed", K(ret));}
  • ObConfigManager::update_local(int64_t expected_version)

該函數(shù)主要做了以下操作:

  1. sql_client_retry_weak.read():從 __all_sys_parameter 內(nèi)部表中讀取增量配置項(xiàng);
  2. system_config_.update():將配置項(xiàng)的新值更新到本地;
  3. reload_config():重新加載和校驗(yàn)配置項(xiàng);
  4. dump2file():將配置項(xiàng)同步到 observer.config.bin 文件中;
int ObConfigManager::update_local(int64_t expected_version)
{int ret = OB_SUCCESS;if (OB_ISNULL(sql_proxy_)) {ret = OB_NOT_INIT;LOG_WARN("sql proxy is null", K(ret));} else {ObSQLClientRetryWeak sql_client_retry_weak(sql_proxy_);SMART_VAR(ObMySQLProxy::MySQLResult, result) {int64_t start = ObTimeUtility::current_time();const char *sqlstr = "select config_version, zone, svr_type, svr_ip, svr_port, name, ""data_type, value, info, section, scope, source, edit_level ""from __all_sys_parameter";if (OB_FAIL(sql_client_retry_weak.read(result, sqlstr))) {LOG_WARN("read config from __all_sys_parameter failed", K(sqlstr), K(ret));} else if (OB_FAIL(system_config_.update(result))) {LOG_WARN("failed to load system config", K(ret));......if (OB_SUCC(ret)) {if ('\0' == dump_path_[0]) {ret = OB_NOT_INIT;LOG_ERROR("Dump path doesn't set, stop read config", K(ret));} else if (OB_FAIL(server_config_.read_config())) {LOG_ERROR("Read server config failed", K(ret));} else if (OB_FAIL(reload_config())) {LOG_WARN("Reload configuration failed", K(ret));} else {DRWLock::RDLockGuard guard(OTC_MGR.rwlock_); // need protect tenant config because it will also serialize tenant configif (OB_FAIL(dump2file())) {LOG_WARN("Dump to file failed", K_(dump_path), K(ret));......

租戶配置項(xiàng)同步
  • ObLeaseStateMgr::HeartBeat::runTimerTask()

......

  • ObTenantConfig::got_version(long, bool)
  • ObTenantConfig::TenantConfigUpdateTask::runTimerTask()

租戶配置項(xiàng)同樣有一個(gè)后臺(tái)定時(shí)任務(wù),只要配置項(xiàng)的最新版本大于本地版本,就會(huì)觸發(fā)更新操作。

void ObTenantConfig::TenantConfigUpdateTask::runTimerTask()
{int ret = OB_SUCCESS;if (OB_ISNULL(config_mgr_)) {ret = OB_NOT_INIT;LOG_WARN("invalid argument", K_(config_mgr), K(ret));} else if (OB_ISNULL(tenant_config_)){ret = OB_NOT_INIT;LOG_WARN("invalid argument", K_(tenant_config), K(ret));} else {const int64_t saved_current_version = tenant_config_->current_version_;const int64_t version = version_;THIS_WORKER.set_timeout_ts(INT64_MAX);if (tenant_config_->current_version_ >= version) {ret = OB_ALREADY_DONE;} else if (update_local_) {tenant_config_->current_version_ = version;if (OB_FAIL(tenant_config_->system_config_.clear())) {LOG_WARN("Clear system config map failed", K(ret));} else if (OB_FAIL(config_mgr_->update_local(tenant_config_->tenant_id_, version))) {LOG_WARN("ObTenantConfigMgr update_local failed", K(ret), K(tenant_config_));} else {config_mgr_->notify_tenant_config_changed(tenant_config_->tenant_id_);}
  • ObTenantConfigMgr::update_local(uint64_t tenant_id, int64_t expected_version)

查詢 __tenant_parameter 內(nèi)部表獲取當(dāng)前租戶的 config,然后將新的數(shù)據(jù)更新到 config中。

int ObTenantConfigMgr::update_local(uint64_t tenant_id, int64_t expected_version)
{SMART_VAR(ObMySQLProxy::MySQLResult, result) {if (OB_FAIL(sql.assign_fmt("select config_version, zone, svr_type, svr_ip, svr_port, name, ""data_type, value, info, section, scope, source, edit_level ""from %s where tenant_id = '%lu'", OB_TENANT_PARAMETER_TNAME, tenant_id))) {} else if (OB_FAIL(sql_client_retry_weak.read(result, exec_tenant_id, sql.ptr()))) {LOG_WARN("read config from __tenant_parameter failed",KR(ret), K(tenant_id), K(exec_tenant_id), K(sql));} else {DRWLock::WRLockGuard guard(rwlock_);ret = config_map_.get_refactored(ObTenantID(tenant_id), config);if (OB_FAIL(ret)) {LOG_ERROR("failed to get tenant config", K(tenant_id), K(ret));} else {ret = config->update_local(expected_version, result);}
  • ObTenantConfig::update_local()

調(diào)用 system_config_.update() 函數(shù)將配置項(xiàng)更新到本地,然后調(diào)用 dump2file() 將配置項(xiàng)持久化到文件中。

int ObTenantConfig::update_local(int64_t expected_version, ObMySQLProxy::MySQLResult &result,bool save2file /* = true */)
{int ret = OB_SUCCESS;if (OB_FAIL(system_config_.update(result))) {LOG_WARN("failed to load system config", K(ret));if (OB_SUCC(ret)) {if (OB_FAIL(read_config())) {LOG_ERROR("Read tenant config failed", K_(tenant_id), K(ret));} else if (save2file && OB_FAIL(config_mgr_->dump2file())) {LOG_WARN("Dump to file failed", K(ret));

小結(jié)

新增配置項(xiàng)并不復(fù)雜,代碼中已經(jīng)實(shí)現(xiàn)了成熟的訪問(wèn)和同步機(jī)制,只需要使用合適的宏并填上一些參數(shù)就可以定義新配置項(xiàng)了,而后續(xù)如何使用這個(gè)配置項(xiàng)才是實(shí)現(xiàn)新功能的關(guān)鍵。在修改配置項(xiàng)的過(guò)程中,實(shí)際上還會(huì)進(jìn)行一些合法性檢查,這部分會(huì)在后面的文章中與系統(tǒng)變量一起進(jìn)行說(shuō)明。

本專題下一篇文章是關(guān)于“系統(tǒng)變量的定義和源碼解析”,系統(tǒng)變量的機(jī)制有別于配置項(xiàng),還有全局級(jí)和會(huì)話級(jí)的區(qū)分,感興趣的同學(xué)歡迎繼續(xù)關(guān)注。

參考資料

  1. 配置項(xiàng)總覽
  2. OceanBase源碼
http://www.risenshineclean.com/news/29215.html

相關(guān)文章:

  • 電子商務(wù)系統(tǒng) 網(wǎng)站建設(shè)百度教育會(huì)員
  • 開(kāi)源網(wǎng)站github最近一周國(guó)內(nèi)熱點(diǎn)新聞
  • 濰坊網(wǎng)站建設(shè)公司有哪些內(nèi)容網(wǎng)店培訓(xùn)教程
  • 個(gè)人興趣圖片集網(wǎng)站建設(shè)b站推廣鏈接
  • 網(wǎng)站頁(yè)面描述深圳網(wǎng)絡(luò)營(yíng)銷推廣招聘網(wǎng)
  • 主流網(wǎng)站開(kāi)發(fā)語(yǔ)言企業(yè)網(wǎng)站有哪些功能
  • 價(jià)錢網(wǎng)站建設(shè)百度官方網(wǎng)首頁(yè)
  • 做商城網(wǎng)站公司seo刷關(guān)鍵詞排名軟件
  • 網(wǎng)站建設(shè)歷史友情鏈接推廣平臺(tái)
  • 個(gè)人網(wǎng)站做電影網(wǎng)站南京seo排名優(yōu)化公司
  • 可以做本地生活服務(wù)的有哪些網(wǎng)站營(yíng)銷型網(wǎng)站建設(shè)服務(wù)
  • 怎么登陸建設(shè)工程網(wǎng)站成都網(wǎng)站快速排名優(yōu)化
  • 零遁nas做網(wǎng)站百度開(kāi)放平臺(tái)登錄
  • 網(wǎng)絡(luò)咨詢網(wǎng)站如何做網(wǎng)絡(luò)營(yíng)銷?
  • WordPress如何設(shè)置站點(diǎn)名稱免費(fèi)b站推廣網(wǎng)站2023
  • 中山網(wǎng)站代運(yùn)營(yíng)百度域名注冊(cè)
  • 濟(jì)寧網(wǎng)站建設(shè)案例展示產(chǎn)品營(yíng)銷方案策劃
  • 企業(yè)宣傳片拍攝思路網(wǎng)站如何做seo排名
  • 做視頻網(wǎng)站如何賺錢品牌推廣的渠道有哪些
  • 基于PHP的家教網(wǎng)站開(kāi)發(fā)環(huán)境谷歌seo服務(wù)商
  • 用六類網(wǎng)站做電話可以嗎長(zhǎng)尾關(guān)鍵詞搜索網(wǎng)站
  • seo網(wǎng)站優(yōu)化推廣怎么做東莞seo優(yōu)化案例
  • 最新新聞熱點(diǎn)事件2024摘抄優(yōu)化大師好用嗎
  • 簡(jiǎn)單的網(wǎng)頁(yè)設(shè)計(jì)代碼記事本專業(yè)的網(wǎng)站優(yōu)化公司排名
  • 做網(wǎng)站口碑比較好的大公司百度聯(lián)系電話多少
  • 知果果網(wǎng)站誰(shuí)做的軟文編輯
  • 淘外網(wǎng)站怎么做網(wǎng)站怎么申請(qǐng)?jiān)趺醋?cè)
  • 個(gè)人做購(gòu)物網(wǎng)站犯法嗎交換鏈接平臺(tái)
  • 做網(wǎng)站用小公司還是大公司2022最火營(yíng)銷方案
  • 2_網(wǎng)站建設(shè)的一般步驟包含哪些刷seo快速排名