private Rank GetRank(BConcurrentKey keyHint) { var Rank = Ranks.GetOrAdd(keyHint, (key) => new Rank()); lock (Rank) { long now = Zeze.Util.Time.NowUnixMillis; if (now - Rank.BuildTime < RebuildTime) { return(Rank); } // rebuild List <BRankList> datas = new List <BRankList>(); int cocurrentLevel = GetConcurrentLevel(keyHint.RankType); for (int i = 0; i < cocurrentLevel; ++i) { var concurrentKey = new BConcurrentKey( keyHint.RankType, i, keyHint.TimeType, keyHint.Year, keyHint.Offset); var rank = _trank.GetOrAdd(concurrentKey); datas.Add(rank); } int countNeed = GetRankCount(keyHint.RankType); switch (datas.Count) { case 0: Rank.TableValue = new BRankList(); break; case 1: Rank.TableValue = datas[0].Copy(); break; default: // 合并过程中,结果是新的 BRankList,List中的 BRankValue 引用到表中。 // 最后 Copy 一次。 BRankList current = datas[0]; for (int i = 1; i < datas.Count; ++i) { current = Merge(current, datas[i]); if (current.RankList.Count > countNeed) { // 合并中间结果超过需要的数量可以先删除。 // 第一个current直接引用table.data,不能删除。 current.RankList.RemoveRange(countNeed, current.RankList.Count - countNeed); } } Rank.TableValue = current.Copy(); // current 可能还直接引用第一个,虽然逻辑上不大可能。先Copy。 break; } Rank.BuildTime = now; if (Rank.TableValue.RankList.Count > countNeed) // 再次删除多余的结果。 { Rank.TableValue.RankList.RemoveRange(countNeed, Rank.TableValue.RankList.Count - countNeed); } } return(Rank); }
// 使用异步方案构建rank。 private void GetRankAsync(BConcurrentKey keyHint, System.Action <Rank> callback) { if (Ranks.TryGetValue(keyHint, out var rank)) { long now = Zeze.Util.Time.NowUnixMillis; if (now - rank.BuildTime < RebuildTime) { callback(rank); return; } } // 异步方式没法锁住Rank,所以并发的情况下,可能多次去获取数据,多次构建,多次覆盖Ranks的cache。 int countNeed = GetRankCount(keyHint.RankType); int concurrentLevel = GetConcurrentLevel(keyHint.RankType); RunGetRank(keyHint, // Action OnHashResult (sessionId, hash, returnCode, BRankList) => { App.Server.TryGetManualContext <ModuleRedirectAllContext>(sessionId) ?.ProcessHash(hash, () => new Rank(), (rank) => { if (returnCode != Procedure.Success) // 只有处理成功的结果才是有效的。 { return(returnCode); } if (rank.TableValue == null) { rank.TableValue = BRankList.CopyIfManaged(); // 本地实现的时候可能返回受管理的数据Bean,此时需要拷贝。 } else { rank.TableValue = Merge(rank.TableValue, BRankList); } if (rank.TableValue.RankList.Count > countNeed) // 合并中间结果超过需要的数量可以先删除。 { rank.TableValue.RankList.RemoveRange(countNeed, rank.TableValue.RankList.Count - countNeed); } return(Procedure.Success); }); }, // Action OnHashEnd (context) => { if (context.HashCodes.Count > 0) { // 一般是超时发生时还有未返回结果的hash分组。 logger.Warn($"OnHashEnd: timeout with hashs: {context.HashCodes}"); } var rank = context.UserState as Rank; rank.BuildTime = Zeze.Util.Time.NowUnixMillis; Ranks[keyHint] = rank; // 覆盖最新的数据到缓存里面。 callback(rank); } ); }
public const long RebuildTime = 5 * 60 * 1000; // 5 min private BRankList Merge(BRankList left, BRankList right) { BRankList result = new BRankList(); int indexLeft = 0; int indexRight = 0; while (indexLeft < left.RankList.Count && indexRight < right.RankList.Count) { if (left.RankList[indexLeft].Value >= right.RankList[indexRight].Value) { result.RankList.Add(left.RankList[indexLeft]); ++indexLeft; } else { result.RankList.Add(right.RankList[indexRight]); ++indexRight; } } // 下面两种情况不会同时存在,同时存在"在上面"处理。 if (indexLeft < left.RankList.Count) { while (indexLeft < left.RankList.Count) { result.RankList.Add(left.RankList[indexLeft]); ++indexLeft; } } else if (indexRight < right.RankList.Count) { while (indexRight < right.RankList.Count) { result.RankList.Add(right.RankList[indexRight]); ++indexRight; } } return(result); }