基于actor模型,系统设计的难点在于抽象业务模型,一旦业务模型稳定,我们完全可以用内存方式来保存对象状态(也可以定时去持久化),内存方式比用其他网络存储(例如redis)要快上几个量级,菜菜也有一篇文章大家可以去撸一下:https://mp.weixin.qq.com/s/6YL3SnSriKEnpCyB5qkk0g ,既满足了一致性,又可以利用进程内对象状态来应对高并发业务场景,何乐而不为呢?
有不少同学问过我,actor模型要避免出现热点问题,就算有内存状态为其加速,那并发数还是超过actor的处理能力怎么办呢? 其实和传统做法类似,所有的高并发系统设计无非就是“分”一个字,无论是简单的负载均衡,还是复杂的分库分表策略,都是分治的一种体现。一台服务器不够,我就上十台,百台.....
所有的高并发系统设计都是基于分治思想,把每一台服务器的能力发挥到极致,难度最大的还是其中的调度算法。
用actor模型来应对高并发,我们可以采用读写分离的思想,主actor负责写请求,并利用某种通信机制把状态的变化通知到多个从actor,从actor负责对外的读请求,这个DB的读写分离思想一致,其中最难的当属actor的状态同步问题了,解决问题的方式千百种,总有一种适合你,欢迎你留言写下你认为最好的解决方案。
案例(玩家信息服务)由于菜菜是c#出身,对c#的Actor服务框架Orleans比较熟悉,这里就以Orleans为例,其他语言的coder不要见怪,Orleans是一个非常优秀的Actor模型框架,而且支持最新的netcore 3.0版本,地址为:https://github.com/dotnet/orleans 有兴趣的同学可以去看一下,而且分布式事物已经出正式版,非常给力。其他语言的也非常出色java:https://github.com/akka/akka
golang:https://github.com/AsynkronIT/protoactor-go
1. 首先我们定义玩家的状态信息
//玩家的信息,其实也就是玩家的状态信息public class Player {
/// <summary>
/// 玩家id,同时也是玩家这个服务的主键
/// </summary>
public long Id { get; set; }
/// <summary>
/// 玩家姓名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 玩家等级
/// </summary>
public int Level { get; set; }
}
2. 接下来定义玩家的服务接口
/// <summary>/// 玩家的服务接口
/// </summary>
interface IPlayerService: Orleans.IGrainWithIntegerKey
{
//获取玩家名称
Task<string> GetName();
//获取玩家等级
Task<int> GetLevel();
//设置玩家等级,这个操作会改变玩家的状态
Task<int> SetLevel(int newLevel);
}
3. 接下来实现玩家服务的接口
public class PlayerService : Grain, IPlayerService{
//这里可以用玩家的信息来代表玩家的状态信息,而且这个状态信息又充当了进程内缓存的作用
Player playerInfo;
public async Task<int> GetLevel()
{
return (await LoadPlayer()).Level;
}
public async Task<string> GetName()
{
return (await LoadPlayer()).Name;
}
public async Task<int> SetLevel(int newLevel)
{
var playerInfo =await LoadPlayer();
if (playerInfo != null)
{
//先进行数据库的更新,然后在更新缓存的状态, 进程内缓存更新失败的几率几乎为0
playerInfo.Level = newLevel;
}
return 1;
}
private async Task< Player> LoadPlayer()
{
if (playerInfo == null)
{
var id = this.GetPrimaryKeyLong();
//这里模拟的信息,真实环境完全可以从持久化设备进行读取
playerInfo= new Player() { Id = id, Name = "玩家姓名", Level = 1 };
}
return playerInfo;
}
}
以上只是一个简单案例,有状态的服务还有更多的设计方案,以上只供参考完