Redis 有序荟萃以及荟萃同样也是 string 类型元素的荟萃,且没有容许反复的成员。
没有同的是每一个元素城市联系关系一个 double 类型的分数。redis 恰是经过分数来为荟萃中的成员进行从小到年夜的排序。
有序荟萃的成员是惟一的,但分数 (score) 却能够反复。
荟萃是经过哈希表完成的,以是增加,删除了,查找的复杂度都是 O (1)。 荟萃中最年夜的成员数为 2^32 - 1^ (4294967295, 每一个荟萃可存储 40 多亿个成员)。
有序荟萃起首是荟萃,其成员(member)具备惟一性,其次,每一个成员联系关系了一个分数(score),使患上成员能够依照分数排序。
需要形容
想象正在一个游戏中,有上百万的玩家数据,假如如今需求你依据玩家的经历值整顿一个前 10 名的排行榜,你会怎样做呢?普通的做法是写一条相似上面这条 sql 语句的形式来猎取:
select * from game_socre order by score desc limit 0,20
这类形式正在数据量较小的状况下可行,然而正在数据量年夜的状况下查问速率将变慢,特地是还需求联表查问时,速率降落的就更显著了。
完成
这时候你能够思考应用 redis 来完成这个性能。
完成这个性能次要用到的 redis 数据类型是 redis 的有序荟萃 zset。zset 是 set 类型的一个扩大,比原本的类型多了一个程序属性。此属性正在每一次拔出数据时会主动调整程序值,保障 value 值依照肯定程序延续陈列。
次要的完成思绪是:
一、正在一个新的玩家参加到游戏中时,正在 redis 中的 zset 中新增一笔记录(记载内容看详细的需要)score 为 0
二、当玩家的经历值发作变动时,修正该玩家的 score 值
三、应用 redis 的 ZREVRANGE 办法猎取排行榜
前往有序集 key 中,指定区间内的成员。此中成员的地位按 score 值递加 (从年夜到小) 来陈列。具备相反 score 值的成员按字典序的反序陈列。 除了了成员按 score 值递加的秩序陈列这一点外,ZREVRANGE 饬令的其余方面以及 ZRANGE 饬令同样。
redis 127.0.0.1:6379> ZADD KEY_NAME SCORE1 VALUE1.. SCOREN VALUEN
一、数据预备
二、猎取 score 高分 top10 排名 (ZREVRANGE 为降序,ZRANGE 为升序)
三、查看用户 ee 的实际排名 (ZREVRANK 为降序,ZRANK 为升序)、及时分数
进一步需要
需求完成比来的 24 小时用户积分排行榜,并统计前 10 名的玩家以及积分
完成
次要的完成思绪是:
行使 ZADD 按小时划分增加用户的积分信息,而后用 ZUNIONSTORE 并集完成 24 小时的游戏积分总以及,完成 “24 小时排行榜”;(假如有更好的思绪,可以正在下方留言不惜见教一下就更好了)
ZUNIONSTORE destination numkeys key [key ...]
Redis Zunionstore 饬令较量争论给定的一个或多个有序集的并集,此中给定 key 的数目必需以 numkeys 参数指定,并 将该并集(后果集)贮存到 destination 。
默许状况下,后果集中某个成员的分数值是一切给定集下该成员分数值之以及 。
可能碰着的成绩
一、相反分数成绩
Redis 正在遇到分数相反时是依照荟萃成员本身的字典程序来排序,这里便是依照”user2″以及”user3″这两个字符串进行排序,以逆序排序的话 user3 天然排到了后面。要处理这个成绩,咱们能够思考正在分数中退出工夫戳,较量争论公式为:
带工夫戳的分数 = 实际分数*10000000000 + (9999999999 – timestamp)
timestamp 咱们采纳零碎提供的 time () 函数,也就是 1970 年 1 月 1 日以来的秒数,咱们采纳 32 位的工夫戳(这能坚持到 2038 年),因为 32 位工夫戳是 10 位十进制整数(最年夜值 4294967295),以是咱们让工夫戳盘踞低 10 位(十进制整数),实际分数则扩展 10^10 倍,而后把两局部相加的后果作为 zset 的分数。思考到要定时间倒序陈列,以是工夫戳这局部需求倒置一下,这即是用 9999999999 减去工夫戳的缘由。当咱们要读取玩家实际分数时,只要去掉后 10 位便可。
初步看起来这个计划还没有错,但这外面有两个成绩。
第一个成绩是小成绩,采纳秒为工夫戳可能区别度还不敷,假如同一秒呈现两个分数相反的依然会呈现后面的成绩,当然咱们能够抉择精度更高的工夫戳,但正在实际场景中,同一秒谁排后面曾经有关紧要。
第二个成绩是年夜成绩,由于 Redis 的分数类型采纳的是 double,64 位双精度浮点数只有 52 位无效数字,它能准确表白的整数范畴为 - 2^53 到 2^53,最高只能示意 16 位十进制整数(最年夜值为 9007199254740992,其实连 16 位也不克不及完好示意)。这就是说,假如后面工夫戳占了 10 位的话,分数就只剩下 6 位了,这关于某些排行榜分数来讲是不敷用的。咱们能够思考缩减工夫戳位数,比方从 2015 年 1 月 1 日开端计时,但这依然添加没有了几位。或许缩小区别度,以分钟、小时来作为工夫戳单元。
假如 Redis 的分数类型为 int64,咱们就不下面的懊恼。说到这里,其实 Redis 真应该再额定提供一个 int64 类型的 ZSet,但今朝只能是空想,除了非本人改其源码。
更多PHP相干常识,请拜访PHP中文网!
以上就是PHP+Redis 有序荟萃完成 24 小时排行榜及时更新的具体内容,更多请存眷资源魔其它相干文章!
标签: php php开发教程 php开发资料 php开发自学 Redis
抱歉,评论功能暂时关闭!