CREATE TABLE `user_info` ( `id` int NOT NULL AUTO_INCREMENT, `user_name` varchar(255) DEFAULT NULL, `age` int DEFAULT NULL, `step` int DEFAULT 0 comment '步数', `picture_url` varchar(255) DEFAULT NULL comment '头像url', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3这时候要实现一个微信步数排行版,不是有手就行嘛:
select * from user_info order by step desc这个实现没有问题的,如果表的数据量少的话,反而推荐这样实现。如果数据量多呢?
for (int i = 0; i < 10000000; i++) { UserInfo record = new UserInfo(); record.setUserName("user" + i); record.setAge(10); record.setUserName("userName" + i); record.setStep(new Random().nextInt(1000) * 1000); record.setPictureUrl("https://tianluo/picture/"+i+".jpg"); userInfoDao.insertUserInfo(record); }我们现在查询步数前1000的用户,SQL如下:
select * from user_info order by step desc limit 0,1000;然后看下耗时,set @@profiling=1;,show profiles;
ALTER TABLE user_info ADD INDEX idx_step (step);添加完索引之后,发现再去查步数前1000的用户,0.005秒:
zadd run:ranking 1000 “小明” zadd run:ranking 3000 “小华” zadd run:ranking 2000 “小红” zadd run:ranking 4000 “小李”我们用这个命令,就可以输出排行榜啦:
ZREVRANGE run:ranking 0 -1 WITHSCORESZREVRANGE 表示从大到小排序
"a" - 1000 "b" - 2000 "c" - 2000 "d" - 3000在这个示例中,成员 "b" 和 "c" 具有相同的分数 2000。当使用 ZRANGE 或 ZREVRANGE 命令来查看有序集合的成员时,它们将按照字典顺序进行排列。因此,成员 "b" 将在成员 "c" 的前面,因为 "b" 的字典顺序小于 "c"。
数据一致性:在多个客户端同时更新排行榜数据时,可能会出现数据不一致的情况。虽然 Redis 提供了一些原子操作来确保数据的一致性,但在高并发的情况下,仍然需要注意数据一致性的问题。
持久化:默认情况下,Redis 将数据存储在内存中,并且可以通过持久化功能将数据写入磁盘。但是,使用持久化功能可能会影响 Redis 的性能,并增加系统的负载。