一、Actor简介

actor模型是一种并行计算的数学模型。 响应于收到的消息,演员可以:做出决定,创建更多Actor,发送更多消息,并确定如何响应接收到的下一条消息。 演员可以修改自己的状态,但只能通过消息相互影响(避免需要任何锁)。

actor是一个计算实体,当其收到消息时,可以并发执行如下操作:

1. 发送有限数量的消息给其他actor

2. 创建有限数量的新actor

3. 指定收到下一消息时的行为

在Orleans中使用的是虚拟Actor方式,详细:http://dotnet.github.io/orleans/Documentation/Introduction.html

详细参见: https://en.wikipedia.org/wiki/Actor_model

二、Orleans框架

Orleans是一个框架,可以直接构建分布式大规模计算应用程序,而无需学习和应用复杂的并发或其他缩放模式。 它是由Microsoft Research创建的,旨在用于云端。

Orleans已被Microsoft Azure广泛应用于微软的几个产品集团,其中最着名的是343个行业,作为所有Halo 4和Halo 5云服务的平台,以及越来越多的其他公司。

特性:

1、默认可扩展
           奥尔良处理构建分布式系统的复杂性,使您的应用程序能够扩展到数百台服务器。
    2、低延迟
           奥尔良允许您保持内存所需的状态,因此您的应用程序可以快速响应传入的请求。

3、简化并发

Orleans允许您编写简单的单线程C#代码,通过actor之间的异步消息传递来处理并发。

三、生成流水号项目实战

1、场景

现在系统基于分布式服务开发,数据在客户端处理后提交到服务端入库,但是由于多个系统间的并发而流水号全部在一张表,每次都是先select在update 高并发容易直接死锁。

如图:

2、基于Orleans的actor

将每条数据改造成一个Actor,由个Actor之间的状态来保证流水号的递增,这样即使单个流水号访问量大只要扩展Orleans的soli即可。

四、关键代码:

1、利用初始化SerialNumberStorgeProvider初始化管理Grain的状态

public class SerialNumberStorgeProvider : IStorageProvider
{
public Logger Log { get; set; } public string Name { get; set; } public Task ClearStateAsync(string grainType, GrainReference grainReference, IGrainState grainState)
{
return TaskDone.Done;
} public Task Close()
{
return TaskDone.Done;
} public Task Init(string name, IProviderRuntime providerRuntime, IProviderConfiguration config)
{
this.Name = nameof(SerialNumberStorgeProvider);
this.Log = providerRuntime.GetLogger(this.Name); return TaskDone.Done;
} public Task ReadStateAsync(string grainType, GrainReference grainReference, IGrainState grainState)
{
Console.WriteLine("获取种子信息");
var SerialNumber = grainReference.GetPrimaryKeyString();
using (var db = new DBContext())
{
var query = db.SerialNumbers.AsNoTracking().FirstOrDefault(o => o.Name.Equals(SerialNumber));
if (query != null)
grainState.State = query;
else
{
db.SerialNumbers.Add(new SerialNumberInfo
{
Name = grainReference.GetPrimaryKeyString(),
Number =
});
db.SaveChanges();
grainState.State = new SerialNumberInfo
{
Name = grainReference.GetPrimaryKeyString(),
Number =
};
}
}
return TaskDone.Done;
} public async Task WriteStateAsync(string grainType, GrainReference grainReference, IGrainState grainState)
{
var model = grainState.State as SerialNumberInfo;
using (var db = new DBContext())
{
var query = db.SerialNumbers.FirstOrDefault(o => o.Name.Equals(model.Name));
query.Number = model.Number;
await db.SaveChangesAsync();
}
}
}
2、Grain获取流水号的实现  
[StorageProvider(ProviderName = "SerialNumberStorgeProvider")]
public class SerialNumberGrain : Grain<SerialNumberInfo>, ISerialNumberGrain
{
/// <summary>
/// 获取多个流水号
/// </summary>
/// <param name="number"></param>
/// <returns></returns>
public Task<List<long>> GetMutilSerialNumber(int number)
{
if (number == ) { number = ; } List<long> list = new List<long>();
for (int i = ; i <= number; i++)
{
this.State.Number += ;
list.Add(this.State.Number);
}
this.WriteStateAsync();
return Task.FromResult(list);
} /// <summary>
/// 获取单个流水号
/// </summary>
/// <returns></returns>
public Task<long> GetSerialNumber()
{
this.WriteStateAsync();
return Task.FromResult(this.State.Number);
}
}

最后,最多说一句,在测试的时候发现如果不适用如下这种方式,并发时会发生Task调度异常

源码地址:https://github.com/liyang-live/MakeSerialNumber

参考资料:http://dotnet.github.io/orleans/index.html

http://www.cnblogs.com/joab/p/5657851.html

https://github.com/dotnet/orleans

Orleans框架------基于Actor模型生成分布式Id的更多相关文章

  1. 基于雪花算法生成分布式ID(Java版)

    SnowFlake算法原理介绍 在分布式系统中会将一个业务的系统部署到多台服务器上,用户随机访问其中一台,而之所以引入分布式系统就是为了让整个系统能够承载更大的访问量.诸如订单号这些我们需要它是全局唯 ...

  2. 基于Actor模型的CQRS、ES解决方案分享

    开场白 大家晚上好,我是郑承良,跟大家分享的话题是<基于Actor模型的CQRS/ES解决方案分享>,最近一段时间我一直是这个话题的学习者.追随者,这个话题目前生产环境落地的资料少一些,分 ...

  3. redis生成分布式id方案

    分布式Id - redis方式   本篇分享内容是关于生成分布式Id的其中之一方案,除了redis方案之外还有如:数据库,雪花算法,mogodb(object_id也是数据库)等方案,对于redis来 ...

  4. Actor模型(分布式编程)

    Actor的目的是为了解决分布式编程中的一系列问题.所有消息都是异步交付的,因此将消息发送方与接收方分开,正是由于这种分离,导致actor系统具有内在的并发性:可以不受限制地并行执行任何拥有输入消息的 ...

  5. 分布式ID系列之为什么需要分布式ID以及生成分布式ID的业务需求

    为什么需要分布式id生成系统 在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识.如在美团点评的金融.支付.餐饮.酒店.猫眼电影等产品的系统中,数据日渐增长,对数据分库分表后需要有一个唯一ID ...

  6. 雪花算法生成分布式ID

    分布式主键ID生成方案 分布式主键ID的生成方案有以下几种: 数据库自增主键 缺点: 导入旧数据时,可能会ID重复,导致导入失败 分布式架构,多个Mysql实例可能会导致ID重复 UUID 缺点: 占 ...

  7. 高系统的分布性有状态的中间层Actor模型

    写在前面 https://www.cnblogs.com/gengzhe/p/ray_actor.html Orleans是基于Actor模型思想的.NET领域的框架,它提供了一种直接而简单的方法来构 ...

  8. 美团分布式ID生成框架Leaf源码分析及优化改进

    本文主要是对美团的分布式ID框架Leaf的原理进行介绍,针对Leaf原项目中的一些issue,对Leaf项目进行功能增强,问题修复及优化改进,改进后的项目地址在这里: Leaf项目改进计划 https ...

  9. 程序员修神之路--🤠分布式高并发下Actor模型如此优秀🤠

    写在开始 一般来说有两种策略用来在并发线程中进行通信:共享数据和消息传递.使用共享数据方式的并发编程面临的最大的一个问题就是数据条件竞争.处理各种锁的问题是让人十分头痛的一件事. 传统多数流行的语言并 ...

随机推荐

  1. visual studio 2013 git 记住密码

    原有配置: C:\Users\Administrator 下.gitconfig内容为 [user] name = lijf4 email = lijf4@lenovo.com 删除,修改为 [cre ...

  2. 終于解決调用wordpress 4.3 xmlrpc api 发布包含分类的文章时返回“抱歉,文章类型不支持您的分类法”错误的問題

    這個問題我找了很多資料都沒有明說是如何解決,后來突發奇想得出我的解決方案如下,所以特此記錄一下: object postId = blogService.NewPost(0,"admin&q ...

  3. Python实现简单登陆验证(文件操作)

    利用python编写一个简单的登陆验证 代码主要功能: 利用Python实现简单的登陆验证,代码主要有两个部分组成: 第一部分:登陆页面,作用是实现用户名和密码的输入 利用两个输入函数input()来 ...

  4. C# SQLite 数据库

    数据库 Oracle.Oracle的应用,主要在传统行业的数据化业务中,比如:银行.金融这样的对可用性.健壮性.安全性.实时性要求极高的业务 MS SQL Server.windows生态系统的产品, ...

  5. Asp.NetCore安全验证之JWT

    本文只是介绍了下基于AspNetCore自带的System.IdentityModel.Tokens.Jwt.dll工具在项目中Token的应用. 我这里谈到的很浅显就两点: 一,超时时间 二,数据的 ...

  6. GO学习笔记 - map

    map是GO语言中的一种高级数据类型,特点是key和value对应,这和Delphi中的Dictionary一样!map的声明格式:map[key数据类型]value数据类型.使用map前,必须用ma ...

  7. Web Api 内部数据思考 和 利用http缓存优化 Api

    在上篇<Web Api 端点设计 与 Oauth>后,接着我们思考Web Api 的内部数据: 其他文章:<API接口安全加强设计方法> 第一  实际使用应该返回怎样的数据 ? ...

  8. linux进程管理(二)

    接上[linux进程管理(一)] 终止进程的工具 kill .killall.pkill 终止一个进程或终止一个正在运行的程序,一般是通过 kill .killall.pkill.xkill 等进行. ...

  9. java中数组的插入

    package com.hxzy.demo; import java.util.Arrays;import java.util.Scanner; public class Demo1 { public ...

  10. scrapy实战2,使用内置的xpath,re和css提取值

      以伯乐在线文章为爬取目标blog.jobbole.com,发现在"最新文章"选项中可看到所有文章   一般来说,可以用scrapy中自带的xpath或者css来提取数据,定义在 ...