排行榜是很多软件的功能需求,比如我们常玩的各类游戏,视频直播,微博等等都有排行榜。现在的排行榜实现方式大都有这两种:1.定时排名,2实时排名,下面就让我来介绍我对实时排行榜的理解。
实时排行有两个问题:
1. 如果数据量很大怎么做到实时排名?
2. 如果要实时调整排名数据怎么做到快速调整?
对于数据量小的程序可以在单个机器上完成就ok了,其实主要的实现方法还是数组移动和排名的映射。
首先声明一个vector数组,用来保存排名数据,数组下标就是名次(当然同样的排名值可以特殊的显示处理)。其次声明一个map或hashmap(hashmap性能会高些)用来存储一个id对应的名次。实现的代码如下:
struct RankData
{
int id;
int value;
RankData() :id(0), value(0){};
};
class RankMgr
{
public:
RankMgr();
virtual ~RankMgr();
bool AddRankData(int id,int value); //添加某个ID的排名数值
bool updateRankData(int id,int value); //更新某个ID的排名数值
bool loadRankData(vector<RankData>& data,int up, int down);//获取把某个id前面up名,后面down名的数值
private:
map<int,int> _ranksMap; //(这里可以用hashmap效率会更高)ID对应的排名位置即ID对应的数组下标位置
deque<RankData> _ranks; //value值有序的数组
};
每添加一个初始的RankData就把它放到数组后面,也把id和对应的数组下标存储到_ranksMap中。当某个排名值改变时,会从_ranksMap找到它对应的数组下标,然后访问数组下标的值,比较旧值和新值得大小,逐个交换并更新ranksMap里面的值。
如果数据量比较大,而且数值变化的范围很大的时候,那上面的办法就需要更进一步的改进了。需要用到不同的桶把每个区间的数据分开并为每个区间预留一些空间,这样可以减少大范围的数据移动,也容易实现数据分布式存储。当某个区间的数据满了的时候可以在相邻的桶之间进行动态调整(从头或从尾插入到可以)。
关于大量数据的存储,可以使用多处缓存定时备份来保存数据,数据库的数据类型为blob类型。