Task是一个很好用的多任务处理类,并且通过Task可以对任务进行很好的控制。
下面将通过代码实现Redis集群在使用IServer.keys时通过多任务对多个服务器示例进行并行计算,并对返回key做汇总计算。
对于主从双服务器的redis使用keys可以很方便的取到所提供的正则匹配KEY集合,但在redis集群中每次只能获取一个redis实例匹配keys,如果先去遍历所有服务器则会十分慢,并且容易出现超时计算,这时我们就用Task为每台Reids服务器做一个异步的Task等待最后一个处理完汇总数据,这样可以大大提升效率。
当然应用在其他地方也是可以的用在任何大批量处理的程序中,掌握Task的使用可谓是一劳永逸。
定义一个异步方法读取redis节点的key
/// <summary> /// 异步任务获取单个Redis匹配keys /// </summary> /// <param name="endpoint">redis节点</param> /// <param name="pattern">匹配的key例如:key:*</param> /// <returns></returns> public async Task<RedisKey[]> GetdkeysbyServer(EndPoint endpoint, string pattern) { var server = RdsCon.GetServer(endpoint); if (server.IsConnected)//判断节点是否可以连接 { if (server.IsSlave)//判断是否为主库,因为存在很多从库,主库断掉后从库会充当主库,所以这里只检查主库数据 { return null; } } else { return null; } var keys = server.Keys(database: Database.Database, pattern: pattern).ToArray(); return keys; }
封装新的keys查询方法
这里主要用到Parallel.ForEach,可以动态创建多个Task,也可以使用Parallel.For。重点:切记这里不能用单纯的for 或者foreach去循环创建Task,即使可以创建,会发现在异步取数据时从第二次年开始每个任务所执行的内容都是相同的。
/// <summary> /// 查找所有符合给定模式 pattern 的 key;KEYS * 匹配数据库中所有 key;KEYS h?llo 匹配 hello,hallo等。KEYS h[ae]llo匹配hello和hallo /// </summary> /// <param name="pattern"></param> /// <returns></returns> public string[] Keys(string pattern) { List<RedisKey> listkey = new List<RedisKey>(); List<Task<RedisKey[]>> arrayTask = new List<Task<RedisKey[]>>(); Parallel.ForEach(RdsCon.GetEndPoints(), item => { Task<RedisKey[]> newtask = GetdkeysbyServer(item, pattern); if (newtask != null) { arrayTask.Add(newtask); } }); Task.WaitAll(arrayTask.ToArray()); foreach (var taskitem in arrayTask) { if (taskitem.Result != null) { listkey.AddRange(taskitem.Result); } } return listkey.Select(e => (string)e).ToArray<string>(); }