根据点击排行榜,将数据显示在引流入口处。
排行榜系统功能:
- 收集相关数据
- 确定排名规则
- 实时性的频率
- 可视化显示:在哪儿以什么形式显示,类别管理等等
- 更新频率:主动干预,保持新鲜度
技术方案
- 新增
- 删除:过期与删除
- 修改:调整分值
- 查询:按类目等进行展示
方案设计
1、使用mysql + order by + 索引优化
优点:数据少业务简单时,维护成本低;
缺点:当数据量大、业务复杂,频繁的查询和更新在Mysql数据库性能降低,高并发情况下,性能会显著降低,多人同时操作时,导致数据不一致,需要采取适当措施保证数据的一致性和正确性。
2、内存堆方案
在涉及到多表存储,但是不推荐联表查询的场景下,可以使用优先级队列[java.util.priorityqueue]来动态维护排行榜信息
日常+考试的分数->在内存中计算->小根堆
实时性的问题:插入和删除时,会自动排序。如果实时更新,需要考虑并发访问的问题和更新的同步问题,并发的读写会导致性能下降、数据的不一致。
内存占用:优先级队列需要在内存中维护排行榜的数据结构,对于大规模的排行榜
,特别是数据量较大时,可能会占用较多的内存。如果排行榜持续增长,内存占用可能成为一个问题。
数据持久化问题:优先级队列是基于内存的数据结构,如果应用程序重启或崩溃,排行榜
数据将丢失。为了实现数据持久化,需要将排行榜数据定期或在特定事
件点保存到持久化存储(如数据库)中。
3、Redis zset
使用Redis的有序集合zset实现排行榜:
- 将新闻的点击次数与新闻title,添加到REDIS的zset中
- ZADD leaderboard <ViewingFrequency> <keyTitle>
- leaderboard 为集合的名称 ,ViewingFrequency 为点击的次数,keyTitle 为新闻的标题
千万数据性能压测:
- 使用python插入千万数据:
-
import redis # Redis连接信息 redis_host = 'localhost' redis_port = 6379 # 生成玩家名称 def generate_keyTitle(index): return "p" + str(index) # 连接到Redis r = redis.Redis(host=redis_host, port=redis_port) # 批量插入数据 for i in range(1, 10000001): keyTitle = generate_keyTitle(i) ViewingFrequency = i r.zadd('leaderboard', {keyTitle: ViewingFrequency}) print("数据插入完成。")
- 查询前100名:
import redis
import time
# Redis连接信息
redis_host = '127.0.0.1'
redis_port = 6379
# 创建Redis客户端
r = redis.Redis(host=redis_host, port=redis_port)
# 测试参数
start_rank = 0
end_rank = 99
num_iterations = 1000
# 执行ZREVRANGE命令并测量性能
total_time = 0
for _ in range(num_iterations):
start_time = time.time()
result = r.zrevrange('leaderboard', start_rank, end_rank, withViewingFrequencys=True)
end_time = time.time()
elapsed_time = end_time - start_time
total_time += elapsed_time
# 打印每次迭代的结果和性能指标
print('Result:', result)
print('Elapsed time:', elapsed_time, 'seconds')
# 打印平均执行时间
average_time = total_time / num_iterations
print('Average time:', average_time, 'seconds')
- 这样在机器不是很差的情况下,一般的查询结果在1ms左右。可以满足大多数企业的要求。
- 修改玩家分数 ZADD leaderboard <ViewingFrequency> <keyTitle>
- 删除玩家分数 ZREM leaderboard <keyTitle>
- 查找指定玩家的排名和分数 ZREVRANK leaderboard <keyTitle>
方案的优点
- Redis的zset集合了MySQL的ORDERBY和内存堆的优点,在大流量、高并发的场景下,推荐优先选取Redis的zset实现排行榜系统。
- 1、增删改查快速
- 2、zset是基于内存的数据结构,数据实时更新,可以通过redis的发布与订阅机制,将变动同步给订阅者。
- 3、zset支持范围查询,也可以查询前多少名
- 4、redis才用了高效的数据结构和内存管理,可以有效的利用内存。
- 5、redis可以进行持久化,可以定期或即时的将数据保存到磁盘上进行持久化