最近抽时间阅读一下OceanBase的源码,就从RootServer开始吧。
OceanBase的RootServer(以下简称Root)的主要功能有集群管理、数据分布以及副本管理。
今天集中研究集群管理:
1、每个集群内部同一时刻只允许有一台UpdateServer(以下简称Update)对外提供写服务,Root通过租约机制选择唯一的主Update,看一看这部分的源码。
//OceanBase中UpdateServer数据结构
struct ObUps
{
common::ObServer addr_;
int32_t inner_port_;
ObUpsStatus stat_;
common::ObiRole obi_role_;
int64_t log_seq_num_;
int64_t lease_;
int32_t ms_read_percentage_;
int32_t cs_read_percentage_;
bool did_renew_received_;
ObUps()
:inner_port_(0), stat_(UPS_STAT_OFFLINE),
log_seq_num_(0), lease_(0),
ms_read_percentage_(0), cs_read_percentage_(0),
did_renew_received_(false)
{
}
void reset();
void convert_to(common::ObUpsInfo &ups_info) const;
};
//选择Master部分
int ObUpsManager::select_ups_master_with_highest_lsn()
{
int ret = OB_ERROR;
if (-1 != ups_master_idx_)
{
TBSYS_LOG(WARN, "cannot select master when there is already one");
ret = OB_UPS_MASTER_EXISTS;
}
else
{
int64_t highest_lsn = -1;
int master_idx = -1;
for (int32_t i = 0; i < MAX_UPS_COUNT; ++i)
{
if (UPS_STAT_OFFLINE != ups_array_[i].stat_)
{
//取log_seq_num_最大的作为Master
if (ups_array_[i].log_seq_num_ > highest_lsn)
{
highest_lsn = ups_array_[i].log_seq_num_;
master_idx = i;
}
}
} // end for
if (-1 == master_idx)
{
TBSYS_LOG(WARN, "no master selected");
}
else
{
change_ups_stat(master_idx, UPS_STAT_MASTER);
ups_master_idx_ = master_idx;
TBSYS_LOG(INFO, "new ups master selected, master=%s lsn=%ld",
ups_array_[ups_master_idx_].addr_.to_cstring(),
ups_array_[ups_master_idx_].log_seq_num_);
ObUps ups(ups_array_[ups_master_idx_]);
refresh_inner_table(ROLE_CHANGE, ups, "null");
reset_ups_read_percent();
ret = OB_SUCCESS;
}
}
return ret;
}
//生成租约部分代码
int ObUpsManager::grant_lease(bool did_force /*=false*/)
{
int ret = OB_SUCCESS;
//对UpdateServer列表加锁保护
tbsys::CThreadGuard guard(&ups_array_mutex_);
ObServer master;
if (has_master())
{
master = ups_array_[ups_master_idx_].addr_;
}
int64_t now = tbsys::CTimeUtil::getTime();
for (int32_t i = 0; i < MAX_UPS_COUNT; ++i)
{
if (UPS_STAT_OFFLINE != ups_array_[i].stat_)
{
//当快到租约到期时间或者强制更新租约的时候(重新选择出Master之后需要强制更新租约)
if (need_grant(now, ups_array_[i]) || did_force)
{
ups_array_[i].did_renew_received_ = false;
//租约到期时间变成当前时间加上租约持续时间
ups_array_[i].lease_ = now + lease_duration_us_;
//生成新的心跳包消息
ObMsgUpsHeartbeat msg;
msg.ups_master_ = master;
msg.self_lease_ = ups_array_[i].lease_;
msg.obi_role_ = obi_role_;
msg.schema_version_ = schema_version_;
msg.config_version_ = config_version_;
//向所有的UpdateServer发送心跳包消息
//此处涉及到rpc调用,源码在ob_root_rpc_stub.cpp中
int ret2 = send_granting_msg(ups_array_[i].addr_, msg);
if (OB_SUCCESS != ret2)
{
TBSYS_LOG(WARN, "grant lease to ups error, err=%d ups=%s",
ret2, ups_array_[i].addr_.to_cstring());
// don't remove the ups right now
}
}
else
{
TBSYS_LOG(DEBUG, "did_renew_received=%c ups=%s", ups_array_[i].did_renew_received_?'Y':'N',
ups_array_[i].addr_.to_cstring());
}
}
}
return ret;
}