6 tracker的选主:relationship_thread_entrance

一、准备工作

1、tracker leader的作用:

tracker server之间是对等的。客户端可以访问任意一台tracker server。
引入tracker leader是为了解决如下问题:
  a. 新加入一台storage server时,由leader指定向其同步的源storage server;
  b. 使用了合并存储特性时,leader为每个group选举和维护唯一的一个trunk server;
以上分配如果不由leader来完成的话,可能会出现混乱情况,尤其是第2条。

2、tracker启动时是不知道其他tracker的存在的。当随后的storage server(storage的配置文件中应当包含所有tracker的ip、port信息)启动时,storage server会去连接每一个tracker,并push 信息。这样tracker的g_tracker_servers才得以初始化(g_tracker_servers初始化在tracker_deal_storage_join->tracker_mem_add_group_and_storage->tracker_mem_first_add_tracker_servers中;后续添加tracker至g_tracker_servers位于tracker_mem_check_add_tracker_servers中)。所有tracker的位置信息都存于g_tracker_servers中,也是用于选主的最关键结构。(一个疑问,在一个正在运行的集群中,如何添加一个tracker server呢?)

3、数据结构

TrackerServerGroup g_tracker_servers = {0, 0, -1, NULL};

typedef struct
{
	int server_count;
	int server_index;  //server index for roundrobin
	int leader_index;  //leader server index
	ConnectionInfo *servers;
} TrackerServerGroup

二、relationship_thread_entrance

static void *relationship_thread_entrance(void* arg)
{
#define MAX_SLEEP_SECONDS  10

	int fail_count;
	int sleep_seconds;

	fail_count = 0;
	while (g_continue_flag)
	{
		sleep_seconds = 1;
		if (g_tracker_servers.servers != NULL)
		{
			if (g_tracker_servers.leader_index < 0)
			{
				if (relationship_select_leader() != 0) //选主。
				{
					sleep_seconds = 1 + (int)((double)rand()
					* (double)MAX_SLEEP_SECONDS / RAND_MAX);
				}
			}
			else
			{
				if (relationship_ping_leader() == 0)  //ping主,发送TRACKER_PROTO_CMD_TRACKER_PING_LEADE命令。
				{
					fail_count = 0;
				}
				else
				{
					fail_count++;
					if (fail_count >= 3)  //超过三次发现leader ping不通,下次循环时就要选择新的leader了。
					{
						g_tracker_servers.leader_index = -1;
					}
				}
			}
		}

		if (g_last_tracker_servers != NULL)
		{
			tracker_mem_file_lock();

			free(g_last_tracker_servers);
			g_last_tracker_servers = NULL;

			tracker_mem_file_unlock();
		}

		sleep(sleep_seconds);
	}

	return NULL;
}

三、relationship_select_leader

static int relationship_select_leader()
{
	int result;
	TrackerRunningStatus trackerStatus;

	if (g_tracker_servers.server_count <= 0)
	{
		return 0;
	}

	logInfo("file: "__FILE__", line: %d, " \
		"selecting leader...", __LINE__);

	if ((result=relationship_get_tracker_leader(&trackerStatus)) != 0) //比较每个tracker的性能(比较函数为relationship_cmp_tracker_status:根据一些参数进行比较即可),得到最佳的tracker存于trackerStatus中。
	{
		return result;
	}

	if (trackerStatus.pTrackerServer->port == g_server_port && \
		is_local_host_ip(trackerStatus.pTrackerServer->ip_addr))
	{//如果就是当前tracker被选中为leader:
		if ((result=relationship_notify_leader_changed( \
				trackerStatus.pTrackerServer)) != 0) //通知所有其他tracker新的leader。
		{
			return result;
		}

		logInfo("file: "__FILE__", line: %d, " \
			"I am the new tracker leader %s:%d", \
			__LINE__, trackerStatus.pTrackerServer->ip_addr, \
			trackerStatus.pTrackerServer->port);

		tracker_mem_find_trunk_servers();
	}
	else
	{
		if (trackerStatus.if_leader)  //如果是这样,就已经知道leader是谁了,不需要等待notify。
		{
			g_tracker_servers.leader_index = \
				trackerStatus.pTrackerServer - \
				g_tracker_servers.servers;
			if (g_tracker_servers.leader_index < 0 || \
				g_tracker_servers.leader_index >= \
				g_tracker_servers.server_count)
			{
				g_tracker_servers.leader_index = -1;
				return EINVAL;
			}

			logInfo("file: "__FILE__", line: %d, " \
				"the tracker leader %s:%d", __LINE__, \
				trackerStatus.pTrackerServer->ip_addr, \
				trackerStatus.pTrackerServer->port);
		}
		else
		{
			logDebug("file: "__FILE__", line: %d, " \
				"waiting for leader notify", __LINE__);
			return ENOENT;
		}
	}

	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值