Redis是一个内存数据库,它最大的作用就是作为缓存使用。提供了多种数据类型,方便开发过程中响应不同的需求场景。要求是这样的。有一些数据需要排序,而且排序不止一个维度。对应数据库,按两个字段综合排序。那么Redis应该使用哪种数据结构呢?先按单个字段排序我们先把问题简化一下,按一个字段排序,看看应该怎么实现。排名场景很常见,比如历史数据排名,热门排名(微博热搜,知乎热榜等,B站热度等),按照播放量排序,如何使用Redis解决这样的问题情景什么?先不考虑实时更新的问题,假设是昨天的榜单,数据已经确定,不会改变。解决方案列表一些人立即想到了使用列表来解决问题。因为列表本身是有序的,所以把列表以Lists的形式放在Redis中。查询的时候直接拿list就行了,什么都不用管。这个方案就是把Redis纯粹当做缓存,存什么存什么取什么,没有任何其他额外的动作。但是这个方案也有缺陷,就是存储的数据已经排序了,所以排序逻辑要提前写在外部程序中,然后把排序后的数据存储在里面。那么如果外部程序没有对列表进行排序,或者条件不允许怎么办呢?那么列表就没有办法了。sortedsetsortedset在Sets的基础上增加了score设置作为排序的依据,所以除了Sets的特性之外,还可以进行排序。它提供了一个score属性,可以作为排序依据,完美契合了列表类别的需求。#按分数从小到大排序ZRANGEkeystartstop[WITHSCORES]#按分数从大到小排序ZREVRANGEkeystartstop[WITHSCORES]使用sortedset可以降低外部程序的复杂度。程序中不需要对列表进行排序,只需要将符合条件的记录取出,保存到sortedset中即可。在sortedset结构中,以访问次数作为分值,查询时执行ZREVRANGE命令。按两个字段排序现在需求变了,排序的维度变了,增加了一个维度。我们也以人气排名为例。之前是按访问量排序,现在是按访问量和评论总和排序。在数据库中体现是这样的:select*frompostorderbyread_count,comment_countdesc这种情况怎么办?解决办法当然是也可以用列表来实现,逻辑还是一样的。你只需要改变外部程序的查询逻辑。之前按一个字段排序,现在按两个排序。有序集sortedset我们知道有序集中只有一个score属性,那么如何利用这个属性实现二维排序呢?这就需要在score属性上做文章了。最简单的实现可以将访问量+评论数的总和作为评分。但是精度太差了。如果访问量足够大,比如几百万的访问量,几千条评论的数量几乎可以忽略不计。最后,实际排序还是按照访问量来排序。但是这个方法其实可以用在少量的访问量上。比如访问量9000和8500的两篇文章分别有100条和700条评论,最后的结果是9100条和9200条。因此,最终的排序结果实际上是8500次观看的那个。正面。如果访问量太大,可以增加评论的权重,比如一条评论等于100或1000次阅读。也可以降低读取量的精度,例如以10,000或100,000为单位。如果用10万作为精度,那么111万和119万都计算为110万。实时榜单除了一些历史数据榜单,还有很多榜单是实时的。在这种情况下,需要保证redis中的数据是实时更新的。如果是实时更新,用列表存储是不合适的。读写redis是为了追求高性能。如果也使用列表存储,意味着外部程序需要对redis操作进行实时排序和更新。可以想象,那样的话,外部程序根本无法实时更新,否则成本会非常高。所以要靠sortedset来解决。您可以使用ZINCRBY命令快速更新已排序元素的分数。比如视频播放音量更新时,更新redis中的值,因为redis的更新速度很快,所以可以实现播放音量的实时更新。因为ZINCRBYkeyincrementmember是依赖sortedset中的分数进行排序的,所以更新成员分数时,查询到的排名信息是实时列表。本文转载自微信公众号“古风筝”,可通过以下二维码关注。转载本文请联系古风筝公众号。
