大数据排行榜分区排序--erlang实现

db表:以玩家id为主键

-record(r_ranking_partition, {
    id = 0,       %% 玩家id
    section = 0,  %% 区id
    rank = 0,     %% 排名
    value = 0,    %% 值
    time = 0,     %% 时间
    info,         %% r_ranking_info
    extra = []
}).

分区ets表:

-record(r_rank_section, {
    section_id = 0,
    rank = []		%% 排行榜 仅有玩家id,按值排序
}).

进程字典区人数:key(区id)-value(该区的人数),根据区id进行排序

原理:

 当有玩家更新时,将数据存放在cache列表,以玩家Id为主键,每隔一段时间执行刷新。刷新时,取旧的区id,根据value值计算新的区id,对两个区内的数据进行排序,并将排名和区间人数更新db表、分区表、区人数。

取排行榜时,根据范围取数据,假设取的是{3,50}排名范围的玩家,只要根据区人数进行计算,获得所在区,从分区表内获得玩家id以及排序,就能获取到玩家具体的排行榜信息。

%% 获取排行榜列表
get_rank_lst_detail(RankKey, StartN, EndN) ->
    RoleIds = get_rank_lst(RankKey, StartN, EndN),
    {_, Lst} = lists:foldl(
        fun(RoleId, {N, Acc}) ->
            Role = get_role(RankKey, RoleId),
            {N+1, [setelement(?RANK_CROSS_RANK, Role, N) | Acc]}
        end, {StartN, []}, RoleIds),
    Lst.
get_rank_lst(RankKey, StartN, EndN) when EndN>=StartN ->
    CountLst = get_count(RankKey),
    Len = EndN-StartN+1,
    Ets = get_ets(RankKey),
    get_rank_lst(CountLst, Ets, StartN, Len, []).

get_rank_lst(_, _Ets, _StartN, 0, Acc) ->
    Acc;
get_rank_lst([], _Ets, _StartN, _, Acc) ->
    Acc;
get_rank_lst([{SectionId, Count} | T], Ets, StartN, Len, Acc) ->
    if
        Count>=StartN ->
            RoleIds = get_section(Ets, SectionId),
            SubLst = lists:sublist(RoleIds, StartN, Len),
            get_rank_lst(T, Ets, 1, Len-length(SubLst), Acc++SubLst);
        true ->
            get_rank_lst(T, Ets, StartN-Count, Len, Acc)
    end.

优点:避免了对大量玩家的排序操作,当有数据更新时仅排序分片的数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值