深度解码mmo游戏服务器一:时间轮的引入

问题引入:在mmorpg游戏中,群战的时候,玩家释放技能,这时候会出现技能冷却时间,每一个技能都是一个定时器,或者在slg游戏中,玩家修建房屋,创建基地,都会产生一个延时操作,等到了指定时间后,完成房屋修建等任务!!!!!

轮询的尴尬:使用一个定时器,定时遍历多个链表,判定链表里面的任务是否到期! 效率低下,每一次遍历都需要筛选定时器,时间复杂度O(n).

多定时器的尴尬:同时创建多个定时器,每个定时器绑定到期任务,多定时器,会加大cpu的负荷,且任务的到期时间不同,必定会产生更多的定时器。

解决方案:时间轮的引入

如果所示:将同一时间的任务放在一起,组成一个链表,图中每个格子分别指向这样一个链表,定时器每到期一次,图中的指针移动一格,如此循环往复,当指针指向某个格子,代表这个链表里面的定时器可能到期(注意,这里是可能,因为时间轮是一个循环的圈,比如运行一圈需要时间50s,那么一个100s的定时器,虽然在槽位1的链表中,但是需要时间轮运行两圈,这个定时器才到期)。

golang 实现的时间轮git地址:https://github.com/yyhero/timewheel

使用示例:

// 创建房屋
func (this *Player) ConstructHouse() {
	fmt.Printf("玩家:%v开始创建房屋,cur houseNum:%v\n", this.id, this.houseNum)

	// 添加定时器,2s之后创建完成
	timewheel.GetInstance().AddTimer(2*time.Second, "001", func() {
		this.houseNum += 50
		fmt.Printf("玩家:%v创建房屋完成,cur houseNum:%v\n", this.id, this.houseNum)
	})
}

// 创建士兵
func (this *Player) ConstructSoldier() {
	fmt.Printf("玩家:%v开始创建房屋,cur soldierNum:%v\n", this.id, this.soldierNum)

	// 添加定时器,5s之后创建完成
	timewheel.GetInstance().AddTimer(5*time.Second, "002", func() {
		this.soldierNum += 20
		fmt.Printf("玩家:%v创建房屋完成,cur soldierNum:%v\n", this.id, this.soldierNum)
	})
}

// 冷却技能
func (this *Player) Cold() {
	fmt.Printf("玩家:%v开始冷却技能 10 seconds\n", this.id)

	// 添加定时器,5s之后创建完成
	timewheel.GetInstance().AddTimer(10*time.Second, "003", func() {
		fmt.Printf("玩家:%v冷却技能完成\n", this.id)
	})
}

猜你喜欢

转载自blog.csdn.net/yyhero1/article/details/81748684