说明:本次实践基于Redis版本3.2.11。

关于SortedSet

首先,我们都知道Redis的SortedSet是可以根据score进行排序的,以手机应用商店的热门榜单排序为例,根据下载量倒序排列,其简单用法如下:

1

2

3

4

5

6

7

8

127.0.0.1:6379> zadd TopApp 12000000 wechat

(integer) 1

127.0.0.1:6379> zadd TopApp 8000000 taobao 10000000 alipay

(integer) 2

127.0.0.1:6379> ZREVRANGE TopApp 0 -1

1) "wechat"

2) "alipay"

3) "taobao"

对SortedSet做一下简单总结:

  1. 默认升序排列,即通过命令 ZRANGE 实现;如果要按照降序排列,需要通过命令 ZREVRANGE 实现;
  2. 当score即得分一样时,按照 字典顺序 对member进行排序,字典排序用的是二进制,它比较的是字符串的字节数组,所以实际上是比较ASCII码。

简单用法介绍完后,接下来给出几种方案,介绍 如何利用Redis实现多维度排序 。同样的,还是以手机应用商店的热门榜单排序为例:首先按照APP的下载量倒序排序,如果下载量一样,则按照最后更新时间倒序排列。

方案1

介绍的第一个方案,并不需要依赖SortedSet,它的实现非常简单,但是需要产品做简单的妥协,即不能实时更新榜单。其实现方案是:定时每隔1分钟(可以由产品确定时间间隔)通过SQL(select * from tb_apps order by download_count desc, updated_time desc limit 300)或者其他方式计算热门榜单,然后把TOP300用List结构保存到缓存中。

说明:根据应用商店的用户行为分析,真实用户很少会预览10页以后的数据,即使有这种用户,我们也可以忽略掉。所以只需要将总计10页,即10x30=300个APP信息用List结构保存即可。分页取数据时,通过lrange命令即可轻松实现。

这种方案虽然简单,但是非常有用。即使不能做到实时,但是并没有影响用户体验。在项目初期需要快速发布,是一个比较推荐的做法。

方案2

方案2就是本文重点介绍的利用SortedSet实现多维度排序。

介绍方案之前,我们再看一下SortedSet排序因子score, 它是一个双精度64位的浮点型数字字符串。+inf和-inf都是有效值 ,能包括的整数范围是-(2^53) 到 +(2^53),或者说是-9007199254740992 到 9007199254740992。

那么,我们如何实现多维度排序呢?答案是 构造一个特殊的score 。以本文案例为例,排序影响因子是下载量和更新时间,那么我们可以构造一个这样特殊的浮点类型的score: 整数部分就是下载量,小数部分就是最后更新时间戳 。

talk is cheap,show me the code。假设有5个app的下载量和最后更新时间分别如下(说明:更新时间只精确到秒):

wechat-下载量:12000000,最后更新时间:1564022201;其score为:12000000.1564022201
qq-下载量:12000000,最后更新时间:1564022222;其score为:12000000.1564022222
tiktok-下载量:9808900,最后更新时间:1563552267;其score为:9808900.1563552267
taobao-下载量:11006600,最后更新时间:1564345601;其score为:11006600.1564345601
alipay-下载量:11006600,最后更新时间:1564345600;其score为:11006600.1564345600

接下来,我们通过如下命令将这5个APP用SortedSet数据类型保存到Redis中:

zadd TopApp 12000000.1564022201 wechat 12000000.1564022222 qq 9808900.1563552267 tiktok 11006600.1564345601 taobao 11006600.1564345600 alipay

保存后,我们看一下排序结果是否符合我们的预期:

1

2

3

4

5

6

127.0.0.1:6379> zrevrange TopApp 0 -1

1) "qq"

2) "wechat"

3) "taobao"

4) "alipay"

5) "tiktok"

写在最后

是不是很完美?

还不完美,这种讨巧的方式只能实现二维排序。如果有三维排序,四维排序呢?这里笔者提供一种实现参考,即 自定义得分权重计算公式 ,这个公式包含所有影响排序的因子,例如:downloadCount*1000+updatedTime。这种实现无论排序维度多少都搞得定,但是需要注意的是,在具体实现时一定注意不要让score溢出。

总结

以上所述是小编给大家介绍的Redis高级玩法之利用SortedSet实现多维度排序的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

$arr = [['1','张三',98,'http://www.img.com/3.jpg'],['2','李四',79,'http://www.img.com/4.jpg'],['3','王五',48,'http://www.img.com/5.jpg'],['4','赵六',85,'http://www.img.com/6.jpg'],['5','钱八',19,'http://www.img.com/8.jpg'],['6','孙吉',38,'http://www.img.com/9.jpg'],['7','张飞',46,'http://www.img.com/f.jpg'],['8','关羽',65,'http://www.img.com/g.jpg'],['9','德玛',73,'http://www.img.com/dm.jpg'],['10','盖伦',73,'http://www.img.com/gl.jpg']
];$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->del('uid');foreach($arr as $k=>$v){$redis->lpush('uid',$v[0]);$redis->set('name_'.$v[0], $v[1]);  $redis->set('score_'.$v[0], $v[2]);  $redis->set('user_img_'.$v[0], $v[3]);  }//外部根据score排序
$sort = ['BY'=>'score_*','SORT'=>'DESC' ,//'LIMIT'=>array(0,3),'GET'=>array('name_*','score_*','user_img_*')
];  echo '<pre>';$res = array_chunk($redis->sort('uid',$sort), 3);foreach($res as $k=>$v){$res[$k]['sort'] = $k+1;
}print_r($res);foreach($res as $k=>$v){$tr.="<tr><td>{$v['sort']}</td><td>{$v[0]}</td><td>{$v[2]}</td><td>{$v[1]}</td></tr>";
}echo '<h1>排行榜</h1>';$html = "<table><tr><th>排名</th><th>用户名</th><th>头像</th><th>分数 </th>> </tr>{$tr}</table>";echo $html;

header("Content-type: text/html; charset=utf-8"); //zset
$arr = [ //产品名   下载量   更新时间  产品图标['wx',986,time(),'http://www.img.cn/wx.jpg'],['qq',986,time()-1,'http://www.img.cn/qq.jpg'],['taobao',425,time()-100,'http://www.img.cn/taobao.jpg'],['sougou',476,time()-10,'http://www.img.cn/sougou.jpg']];$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$topName = 'topApp';
$redis->del($topName);//先清空//把下载次数和更新时间连接  进行排序
foreach($arr as $k=> $v){$redis->zadd($topName,$v[1].$v[2],$v[0].'_'.$v[3]);
}echo '<pre>';
//print_r( $redis->zscan($topName, 0, 'match','wx_*', 1) ) ;
print_r($redis->zrevrange($topName,0,-1));

Redis高级玩法之利用SortedSet实现多维度排序的方法相关推荐

  1. 微软推出的Prompt高级玩法,包括小样本和任务分解等,简直不要太详细:Azure OpenAI 的提示工程技术

    搜索 打开App 微软推出的Prompt高级玩法,包括小样本和任务分解等,简直不要太详细:Azure OpenAI 的提示工程技术 8 小时前 ChatGPT云炬学长 ChatGPT云炬学长 ​关注 ...

  2. 【ASP.NET Core】依赖注入高级玩法——如何注入多个服务实现类

    依赖注入在 ASP.NET Core 中起中很重要的作用,也是一种高大上的编程思想,它的总体原则就是:俺要啥,你就给俺送啥过来.服务类型的实例转由容器自动管理,无需我们在代码中显式处理. 因此,有了依 ...

  3. 12面魔方公式图解法_【高级篇】(三)三阶魔方CFOP高级玩法之——F2L

    一.F2L这一步要干什么 1.先了解一下"棱角对"和"槽位"的概念 棱角对:即由一个棱块和一个角块构成,是F2L的基本单元(共四组) 槽位:给"棱角对 ...

  4. SkyWalking之高级玩法

    导读 SkyWalking是基于javaagent的两大字节码操作工具之一的Byte Buddy实现的无侵入APM(application performance monitor) 系统,目前项目在A ...

  5. Vim的几个高级玩法

    文章目录 vim的几种模式 扩展命令模式命令: 命令模式高频命令: 命令模式进阶命令: vim高级玩法 小结:  在Linux中编辑文件的场景非常之多,掌握一些关键命令和技巧.能够大大提高效率,使用体 ...

  6. 涨知识!原来华为手机摄像头还有这些高级玩法,学会轻松提高工作效率

    众所周知,华为手机广受用户的喜爱,主要是因为华为手机的实用性强,并且拍照能力也是世界顶尖水平.不过你知道吗?拍照与办公融合,将解锁华为手机摄像头的高级玩法,今天笔者就分享两个,不仅有趣还非常实用的摄像 ...

  7. java enum枚举类的用法以及高级玩法

    enum(枚举)类介绍 java枚举类是一组预定义常量的集合,使用enum关键字声明这个类,常量名称官方建议大写 1.enum类基本用法 举一个常见的例子,例如星期就可以描述为一个枚举类,如下 pub ...

  8. vnc移植_【安富莱】开源原创高级玩法,用F429接SDRAM虚拟远程VNC桌面

    [安富莱]开源原创高级玩法,用F429接SDRAM虚拟远程VNC桌面说明: 0. 这个项目的可玩性极高,可以做很多有意思的应用.做一些远程智能控制尤其方便,省去了学习html,xml,js等麻烦,且无 ...

  9. 魔方cfop公式软件_【高级篇】(三)三阶魔方CFOP高级玩法之——F2L

    一.F2L这一步要干什么 1.先了解一下"棱角对"和"槽位"的概念 棱角对:即由一个棱块和一个角块构成,是F2L的基本单元(共四组) 槽位:给"棱角对 ...

最新文章

  1. nexys3使用笔记1
  2. Spring Boot2.x-07Spring Boot2.1.2整合Mybatis
  3. Vue2.x 踩坑与总结
  4. SAP Fiori应用中事务锁的实现 - Transaction Lock实现机制
  5. C高级第一次PTA作业(2)
  6. 前端基础:html基础(css基础和JavaScript基础)/01/B/S网络结构,html文件结构,html标签格式,lt;bodygt;中的一些常用标记
  7. 无线移动通信基础知识
  8. NO.4 Android开发中常用框架及工具
  9. vim php psr,VIM-PHPer的福利, 将你的VIM打造成为不次于PHPStorm的IDE
  10. 苹果春季发布会:绝不玩别人玩剩下的!
  11. 安装McAfee 8.7i 提示错误1920怎么办?
  12. java自动化测试之开发工具eclipse安装配置
  13. 暗黑主题(皮肤)资源 (实用)
  14. 解决国外软件官网打不开,浏览器访问经常卡在正在建立TLS握手安全连接。
  15. 电子元器件识别(图解)
  16. 360 Replugin 插件化 支持 Androidx和Java8
  17. echart图表去掉空白部分
  18. 大S首度曝光女儿正面照:小小幸福分享给大家
  19. 红米5 Android 8.0,红米 5 获得 Android 8.0 稳定版更新:修复大量问题
  20. RabbitMQ-基础知识总结

热门文章

  1. Python将字符串类标签更改为int
  2. “技术人”频道头条新闻断链
  3. 模拟新闻APP显示界面
  4. spring boot 分布式事务解决方案
  5. 0802-0803 category/product/[order]/orderitem/[user]
  6. GoogleNet 网络结构
  7. Hive中explode的用法
  8. Linux虚拟机克隆后的ip设置(原虚拟机网卡设置为静态ip)
  9. Oracle客户端本地连接配置
  10. android个人理财通项目_公告|MNSC项目周报(2019.03.11—2019.03.20)