标签:需求 大于 注册 elf reg 单机 manager size disco
假设我们这样一个需求:每天晚上定时将数据库数据刷新到缓存中。数据库为 10 库 10 表。每张表 100 万数据。
10库10表总共1亿条数据,各条数据只要序列化为字符串,存入缓存即可,相互无关联。但数据量较大,单机多线程执行的情况下,执行性能也是极慢的。所以我们考虑集群的方式处理。
可以将10库10表拆分为100个task,集群节点不停的拉取task,处理相关逻辑直至所有task处理完成。
为什么要集群,而不能在单机上开多个线程处理?
答:单机多线程处理也有性能上线,当线程启动过多,并发性能会因为线程切换的消耗反而会急剧下降。
定时JOB服务:QuartzJob+Topshelf 组件 来实现windows服务方式部署的定时任务。
集群任务消费:自定义组件 gt.TaskScheduler ,项目源码:https://gitee.com/gt1987/gt.TaskScheduler。
角色定义
集群流程:
集群状态,以KEY-VALUE方式存储在分布式组件中。以Redis为例
具体状态:
/// <summary> /// 节点状态 /// </summary> public enum MemberStatus { /// <summary> /// 已注册 /// </summary> Register = 1, /// <summary> /// 执行任务中 /// </summary> Run = 2, /// <summary> /// 已停止 /// </summary> Stop = 4 } /// <summary> /// 集群 /// </summary> public enum TaskSchedulerStatus { /// <summary> /// 集群启动 /// </summary> Start=1, /// <summary> /// 运行中 /// </summary> Run=2, /// <summary> /// 集群停止 /// </summary> Stop=4 }
启动方式
public void DefaultBuildTest() { var schedulerName = "build_test"; using (var distribute = new RedisDistributeFeature(_redisConn, 3, 10)) { TaskSchedulerManagerBuilder builder = new TaskSchedulerManagerBuilder(schedulerName, distribute); builder.AddTaskHandler("sample1", new SampleHandler(distribute)); builder.AddTaskHandler("sample2", new SampleHandler(distribute)); var taskScheduler = builder.Build(); taskScheduler.Run(); Assert.Equal("0", distribute.GetData(_sampleKey, "sample1")); Assert.Equal("0", distribute.GetData(_sampleKey, "sample2")); } }
SampleHandler:
public class SampleHandler : ITaskHandler { private IDistributeFeature _distribute; private readonly string _sampleKey = "ts:test:sample:result"; public SampleHandler(IDistributeFeature distribute) { _distribute = distribute; } public Task Execute(string tag) { _distribute.SetData(_sampleKey, tag, "0"); return Task.Delay(500); } }
不列详细代码了,具体可参考源码
既存问题:
答1:考虑状态类数据存储增加时间过期,这里的过期时间应该大于整个集群任务完成的预估时间
标签:需求 大于 注册 elf reg 单机 manager size disco
原文地址:https://www.cnblogs.com/gt1987/p/12696864.html