排行榜算法(rbtree skiplist)性能比较

前言

关于几种主流排行榜方案,这里有一个链接,说的挺好的
https://gameinstitute.qq.com/community/detail/101951#

使用redis的zset是比较方便的,他其实也是基于skiplist的。
故而自己分别基于rbtree 和skiplist的方案,写了两份排行榜用的排序树,测试了一下性能。
代码地址: https://github.com/lionel84/rank.git

使用示例

    std::vector<rank_data_value_t > test_data;
    std::vector<rank_data_value_t > test_data_for_rb_tree;
    for(int i = 0; i< nMaxCount; i++){
        test_data.push_back(std::move(rank_data_value_t(i,random(), random())));
        test_data_for_rb_tree.push_back(rank_data_value_t(i,random(), random()));
    }

    RankSkipList<rank_data_key_t, rank_data_value_t, std::greater<rank_data_value_t> > rank_skiplist;
    rank_tree<rank_data_key_t, rank_data_value_t, std::greater<rank_data_value_t> > rank_rbtree;
    
    for(const auto& it : test_data){
        rank_skiplist.zslInsert(std::make_pair(it._uid, it));
    }
    for(const auto& it : test_data_for_rb_tree){
        rank_rbtree.insert(std::make_pair(it._uid, it));
    }

优化:

1 两种算法均需要在erase的时候释放节点,insert的时候申请节点; 所以内置了一个free_list,用于保存erase的节点,在insert的时候从free_list里面申请,避免内存申请释放开销以及碎片的产生,可以更好的持续运行。
2 对begin和back进行了缓存维护,当设置了榜单最大数量时,可以快速进行是否上榜的检查。
3 skiplist的优化:相较于redis的实现,将节点在每层上均设置为双向,可以直接通过节点获取需要更新的前置每层节点(redis中是通过大小比较获取),这样可以在更新数据时,直接将新积分更新到节点上(redis的zset实现无法做到这一点)
4 rbtree获取连续排名对象时,参考skiplist做法,通过对前一个排名的简单操作(next),也可以比较快速的获取结果,千万比较每个都去find,如果数量大的时候,O(nlgn)的开销还是难以承受的。
5 通过传入std::less or std::greater ,同时实现rank_data的小于或大于操作符,可以方便进行小的排前面或者大的排前面。

测试:

机器配置
Cpu:
8核
cpu MHz : 2595.124
cache size : 512 KB
内存:
16G
对于1kw级别数据,O2优化
在这里插入图片描述
总体上看,rbtree的性能和内存消耗要优于skiplist

算法比较:

时间复杂度
两个算法的操作耗时基本上都是lg(n)的。单次操作开销均在us级别
内存占用
rbtree的每个节点大小一致,可以方便进行管理,比较容易使用共享内存机制。skiplist实现需要每个节点保存多层的前后向节点指针,需要额外的开销。
skiplist的优势在于获取连续排名的对象,因为是链表,会比较方便,rbtree通过优化后的方法获取会比skiplist稍慢。

实施:

如果不想折腾,可以直接接入redis,各云服务器也有这样的服务,相对会比较快速。
自己部署rank_svr的话,我比较偏向于使用rbtree的实现方式。
架构上可以设计为双主或者多主进行容灾方案,通过对玩家id路由到各svr节点,对于更新操作(写),由接收端进行落db操作,同时广播给其他节点。对于请求排名操作(读),接受节点直接给结果,不执行广播。宕机后直接从其他节点同步,最糟糕也可以从db恢复,架构简单无锁,性能好;不能保证实时一致,保证最终一致性。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值