博客
关于我
Orleans框架------基于Actor模型生成分布式Id
阅读量:795 次
发布时间:2023-02-26

本文共 3244 字,大约阅读时间需要 10 分钟。

Actor模型与Orleans框架:生成流水号项目实践

在分布式服务开发中,流水号管理是一个关键问题。传统的方法容易导致高并发下的死锁,而使用Actor模型和Orleans框架可以有效解决这一问题。

Actor模型简介

Actor模型是一种并行计算模型,响应消息时可以执行以下操作:

  • 发送有限数量消息给其他Actor
  • 创建有限数量新Actor
  • 指定下一条消息的处理方式
  • Orleans框架采用虚拟Actor方式,提供了简便的编写方式,使开发者无需复杂的并发管理。

    Orleans框架特点

    Orleans框架具有以下优势:

  • 默认可扩展:支持分布式部署,扩展至数百台服务器
  • 低延迟:保持状态在内存,快速响应请求
  • 简化并发:通过异步消息传递实现并发处理
  • 流水号项目实践

    项目背景

    传统流水号管理方式:

    • 数据全局锁,高并发时容易死锁
    • 难以扩展,性能瓶颈严重

    Orleans解决方案

    采用Orleans Actor模型,每条数据作为一个Actor,通过状态共享实现流水号递增。这种方式下,单个流水号访问即可扩展至Orleans支持的规模。

    代码实现

    序列号存储提供器

    public class SerialNumberStorgeProvider : IStorageProvider
    {
    public Logger Log => get; set;
    public string Name => get; set;
    public Task ClearStateAsync(GrainReference grainReference)
    {
    return TaskDone.Done;
    }
    public Task Close()
    {
    return TaskDone.Done;
    }
    public Task Init(string name, IProviderRuntime runtime, IProviderConfiguration config)
    {
    this.Name = name;
    this.Log = runtime.GetLogger(this.Name);
    return TaskDone.Done;
    }
    public Task ReadStateAsync(GrainReference grainReference, IGrainState grainState)
    {
    var serialNumber = grainReference.GetPrimaryKeyString();
    using (var db = new DBContext())
    {
    var query = db.SerialNumbers.AsNoTracking().FirstOrDefault(
    o => o.Name == serialNumber);
    if (query != null)
    {
    grainState.State = query;
    }
    else
    {
    db.SerialNumbers.Add(new SerialNumberInfo
    {
    Name = serialNumber,
    Number = 1
    });
    db.SaveChanges();
    grainState.State = new SerialNumberInfo
    {
    Name = serialNumber,
    Number = 1
    };
    }
    }
    return TaskDone.Done;
    }
    public async Task WriteStateAsync(GrainReference grainReference, IGrainState grainState)
    {
    var model = grainState.State as SerialNumberInfo;
    using (var db = new DBContext())
    {
    var query = db.SerialNumbers.FirstOrDefault(
    o => o.Name == model.Name);
    query.Number = model.Number;
    await db.SaveChangesAsync();
    }
    }
    }

    序列号获取

    [StorageProvider(ProviderName = "SerialNumberStorgeProvider")]
    public class SerialNumberGrain : Grain
    {
    public async Task
    > GetMultiSerialNumber(int number)
    {
    if (number == 0) number = 1;
    var list = new List
    ();
    for (int i = 1; i <= number; i++)
    {
    this.State.Number += 1;
    list.Add(this.State.Number);
    }
    await this.WriteStateAsync();
    return Task.FromResult(list);
    }
    public async Task
    GetSerialNumber()
    {
    await this.WriteStateAsync();
    return this.State.Number;
    }
    }

    注意事项

    测试发现,若不使用上述方式,多线程会导致Task调度异常。使用Orleans Actor模型可以有效避免此问题。

    参考资料

    • Orleans框架官方文档:http://dotnet.github.io/orleans/Documentation/Introduction.html
    • 相关技术博客:http://www.cnblogs.com/joab/p/5657851.html
    • Orleans项目源码:https://github.com/dotnet/orleans

    转载地址:https://www.cnblogs.com/liyangLife/p/7082947.html

    你可能感兴趣的文章
    Orderer节点启动报错解决方案:Not bootstrapping because of 3 existing channels
    查看>>
    org.apache.axis2.AxisFault: org.apache.axis2.databinding.ADBException: Unexpected subelement profile
    查看>>
    sql查询中 查询字段数据类型 int 与 String 出现问题
    查看>>
    org.apache.commons.beanutils.BasicDynaBean cannot be cast to ...
    查看>>
    org.apache.dubbo.common.serialize.SerializationException: com.alibaba.fastjson2.JSONException: not s
    查看>>
    sqlserver学习笔记(三)—— 为数据库添加新的用户
    查看>>
    org.apache.http.conn.HttpHostConnectException: Connection to refused
    查看>>
    org.apache.ibatis.binding.BindingException: Invalid bound statement错误一例
    查看>>
    org.apache.ibatis.exceptions.PersistenceException:
    查看>>
    org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned
    查看>>
    org.apache.ibatis.type.TypeException: Could not resolve type alias 'xxxx'异常
    查看>>
    org.apache.poi.hssf.util.Region
    查看>>
    org.apache.xmlbeans.XmlOptions.setEntityExpansionLimit(I)Lorg/apache/xmlbeans/XmlOptions;
    查看>>
    org.apache.zookeeper.KeeperException$ConnectionLossException: KeeperErrorCode = ConnectionLoss for /
    查看>>
    org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:processDebugManifest'
    查看>>
    org.hibernate.HibernateException: Unable to get the default Bean Validation factory
    查看>>
    org.hibernate.ObjectNotFoundException: No row with the given identifier exists:
    查看>>
    org.springframework.amqp.AmqpConnectException:java.net.ConnectException:Connection timed out:connect
    查看>>
    org.springframework.beans.factory.BeanDefinitionStoreException
    查看>>
    org.springframework.boot.context.properties.ConfigurationBeanFactoryMetadata
    查看>>