使用Redis實現實時排行榜

為了實現一個實時排行榜系統,我們可以使用Redis的有序集合(ZSet),其底層通常是使用跳躍表實現的。有序集合允許我們按照分數(score)對成員(member)進行排序,因此非常適合用來實現排行榜。本文首先介紹有序集合及其底層數據結構——跳表,然后使用Python和Redis結合,展示一個簡單的排行榜系統。

一、ZSet 概述

1.1 ZSet 介紹

實現一個排行榜,很多人可能首先想到的是使用MySQL的order by來排序。然而,當數據量達到百萬級別時,使用數據庫排序的代價是很大的。因此,Redis的有序集合(ZSet)成為了一個更好的選擇。

ZSet(Sorted Set)的特點如下:

  • 唯一性:集合內的元素(成員)是唯一的。
  • 有序性:與普通Set的無序性不同,ZSet的成員是“有序的”,這種有序性是基于成員所關聯的“分數”(score)進行排序的,分數是浮點類型。

1.2 Zset 底層原理

ZSet 是Redis中的一種復雜數據結構,它在Set的基礎上增加了一個權重參數score,使得集合中的元素能按score進行有序排列。

ZSet的底層實現通常有兩種數據結構:

  1. 當元素數量較少或元素長度較短時,采用壓縮列表(ziplist)
  2. 當元素數量達到一定量或者元素長度超過一定限制時,采用跳躍表(skiplist)

跳表(skiplist)具有多層鏈表結構,查詢、插入和刪除操作的平均時間復雜度均為O(log n)。

1.3 ZSet 主要操作命令

  • ZADD key score member:將元素及其分數添加到有序集合中。
  • ZINCRBY key increment member:為有序集合中的元素增加或減少分數。
  • ZRANGE key start stop [WITHSCORES]:獲取有序集合中分數從小到大的排名在指定范圍內的成員。
  • ZREVRANGE key start stop [WITHSCORES]:獲取有序集合中分數從大到小的排名在指定范圍內的成員。
  • ZRANK key member:獲取成員在有序集合中的排名(從小到大的排名,排名從0開始)。
  • ZREVRANK key member:獲取成員在有序集合中的排名(從大到小的排名,排名從0開始)。
  • ZSCORE key member:獲取成員在有序集合中的分數。
  • ZCARD key:獲取有序集合的基數,即成員數量。

二、使用 Redis 和 Python 實現實時排行榜

下面是一個使用Python的redis庫來操作ZSet并實現實時排行榜的示例。

2.1 安裝所需的庫

首先確保已經安裝redis庫:

pip install redis

2.2 初始化RedisLeaderboard類

接下來,我們實現一個RedisLeaderboard類來管理排行榜:

import redis
from flask import Flask, render_template
import sysapp = Flask(__name__)# Initialize Redis connection with error handling
try:r = redis.Redis(host='192.168.88.139',password='123456',port=6379,db=0,socket_connect_timeout=3,  # 3 seconds timeoutdecode_responses=True  # Automatically decode responses to UTF-8)# Test the connectionr.ping()print("成功連接Redis", file=sys.stderr)
except redis.ConnectionError as e:print(f"連接Redis失敗: {e}", file=sys.stderr)r = None  # Set to None so we can check later@app.route('/')
def leaderboard():if r is None:return render_template('error.html',message="Redis server is not available"), 503try:top_10 = get_top_n(10)return render_template('leaderboard.html', leaderboard=top_10)except redis.RedisError as e:return render_template('error.html',message=f"Redis error: {str(e)}"), 500def get_top_n(n):try:top_n = r.zrevrange("game_leaderboard", 0, n - 1, withscores=True)leaderboard = []for rank, (user_id, score) in enumerate(top_n, start=1):leaderboard.append({"rank": rank,"user_id": user_id,  # No need to decode with decode_responses=True"score": float(score)})return leaderboardexcept redis.RedisError as e:print(f"Redis operation failed: {e}", file=sys.stderr)raise  # Re-raise the exception to be handled by the routeif __name__ == '__main__':app.run(debug=True)

在這里插入圖片描述

2.3 案例數據

import redisr = redis.Redis(host='192.168.88.139', password='123456', port=6379, db=0)def add_score(user_id, score):r.zadd("game_leaderboard", {user_id: score})def update_score(user_id, score):r.zincrby("game_leaderboard", score, user_id)def get_top_n(n):top_n = r.zrevrange("game_leaderboard", 0, n - 1, withscores=True)leaderboard = []for rank, (user_id, score) in enumerate(top_n, start=1):leaderboard.append({"rank": rank,"user_id": user_id.decode("utf-8"),"score": score})return leaderboarddef get_user_rank_and_score(user_id):rank = r.zrevrank("game_leaderboard", user_id)if rank is not None:rank += 1score = r.zscore("game_leaderboard", user_id)return rank, scoreif __name__ == '__main__':# 添加初始得分add_score('user1', 100)add_score('user2', 150)add_score('user3', 50)# 更新得分(加分操作),如果用戶不存在,會將其得分初始化為該值update_score('user1', 30)update_score('user2', 20)update_score('user3', -10)# 獲取前2名的用戶top_2 = get_top_n(2)for entry in top_2:print(f"Rank {entry['rank']}: UserID: {entry['user_id']} with score {entry['score']}")# 獲取特定用戶的排名和得分rank, score = get_user_rank_and_score('user1')if rank is not None and score is not None:print(f"User user1 is ranked {rank} with a score of {score}.")else:print("User user1 is not found in the leaderboard.")

2.4 前端

需要創建一個templates文件夾,并在其中存放leaderboard.html文件:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Leaderboard</title><style>table {width: 100%;border-collapse: collapse;}th, td {border: 1px solid black;padding: 8px;text-align: left;}</style>
</head>
<body><h1>Leaderboard</h1><table><thead><tr><th>Rank</th><th>User ID</th><th>Score</th></tr></thead><tbody>{% for entry in leaderboard %}<tr><td>{{ entry.rank }}</td><td>{{ entry.user_id }}</td><td>{{ entry.score }}</td></tr>{% endfor %}</tbody></table>
</body>
</html>

三、結論

Redis的有序集合(ZSet)由于其高效的插入、刪除、查詢及排序操作,是實現實時排行榜的理想選擇。跳表作為ZSet的底層數據結構之一,保證了這些操作的時間復雜度為O(log n)。結合Python的redis庫,可以快速實現一個功能強大、高效的實時排行榜系統。

這種排行榜實現方案非常適合用于在線游戲、社交平臺等各種應用場景。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/76403.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/76403.shtml
英文地址,請注明出處:http://en.pswp.cn/web/76403.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux——firewalld防火墻(筆記)

目錄 一&#xff1a;Firewalld防火墻的概述 &#xff08;1&#xff09;firewalld簡介 &#xff08;2&#xff09;firewalld&iptables的關系 &#xff08;3&#xff09;firewalld與iptables service的區別 1. ?規則管理方式? 2. ?默認策略與設計邏輯? 3. ?配置文…

JS中實現類似sleep、wait、delay的延時功能

前言 編寫代碼時很多時候需要進行流程化的操作&#xff0c;各個流程間通常需要等待一定時間&#xff0c;這在很多語言中通常可以使用 sleep 、 wait 、 delay 等函數來實現。JavaScript原生并沒有類似的功能&#xff0c;想要延時通常就是使用 setTimeout(functionRef, delay) …

Elasticsearch:使用 ES|QL 進行搜索和過濾

本教程展示了 ES|QL 語法的示例。請參考 Query DSL 版本&#xff0c;以獲得等效的 Query DSL 語法示例。 這是一個使用 ES|QL 進行全文搜索和語義搜索基礎知識的實踐介紹。 有關 ES|QL 中所有搜索功能的概述&#xff0c;請參考《使用 ES|QL 進行搜索》。 在這個場景中&#x…

Java 動態代理實現

Java 動態代理實現 一、JDK動態代理二、CGLIB動態代理三、動態代理的應用場景四、JDK代理與CGLIB代理比較 動態代理是Java中一種強大的技術&#xff0c;它允許在運行時創建代理對象&#xff0c;用于攔截對目標對象的方法調用。 一、JDK動態代理 JDK動態代理是Java標準庫提供的代…

Apache IoTDB V2.0.2/V1.3.4 發布|新增表模型權限管理、UDF、嵌套查詢功能

Release Announcement Version 2.0.2/1.3.4 Apache IoTDB V2.0.2、V1.3.4 已經發布&#xff01; V2.0.2 作為樹表雙模型正式版本&#xff0c;主要新增表模型權限管理、用戶管理以及相關操作鑒權&#xff0c;并新增了表模型 UDF、系統表和嵌套查詢等功能。 V1.3.4 主要新增模式…

鴻蒙開發11-ARKUI框架

ARKUI&#xff08;方舟 UI 框架&#xff09;是 HarmonyOS Next&#xff08;原 OpenHarmony&#xff09;的核心 UI 開發框架&#xff0c;基于聲明式編程范式&#xff0c;支持 ArkTS 語言&#xff0c;能夠高效構建跨設備的響應式應用。以下是對 ARKUI 框架及開發的詳細介紹&#…

Linux 進程間通信詳解

一.進程間通信介紹 1. 進程間通信概念 進程間通信&#xff08;Inter-Process Communication, IPC&#xff09;是指在不同進程之間傳遞或交換信息的一種機制。在操作系統中&#xff0c;進程是資源分配和獨立運行的基本單位&#xff0c;它們擁有各自獨立的內存空間和系統資源。…

從0開始掌握動態規劃

動態規劃的核心思想 -- 以空間換時間 復雜點說通過分解問題為子問題并存儲子問題解來優化復雜計算的算法策略。 簡單看個問題。 一&#xff0c;初始&#xff1a;求最長連續遞增子序列 nums [10,9,2,5,3,7,101,18] 求上面數組中的最長連續遞增子序列&#xff0c;輸出其長度 …

Python Requests 庫:從安裝到精通

摘要 本文詳細介紹 Python Requests 庫的安裝與使用&#xff0c;通過常見示例讓你輕松掌握。 一、引言 在當今的互聯網時代&#xff0c;與各種 Web 服務進行交互是非常常見的需求。Python 作為一門功能強大且易于學習的編程語言&#xff0c;提供了許多用于網絡請求的庫&…

Manus技術架構、實現內幕及分布式智能體項目實戰

Manus技術架構、實現內幕及分布式智能體項目實戰 模塊一&#xff1a; 剖析Manus分布式多智能體全生命周期、九大核心模塊及MCP協議&#xff0c;構建低幻覺、高效且具備動態失敗處理能力的Manus系統。 模塊二&#xff1a; 解析Manus大模型Agent操作電腦的原理與關鍵API&#xf…

C算術運算符 printf輸出格式 字符指針打印輸出 使用scanf函數進行輸入

一 算術運算符 加, 一元取正 - 減, 一元取負 * 乘 / 除 % 求余 -- 自減1 自加1 邏輯運算符 && 邏輯與 || 邏輯或 ! 邏輯非 關系運算符 > 大于 > 大于等于 < 小于 < 小于等于 等于 ! 不等于 位運算符號 & 按位與 | 按位或 ^ 按位異或…

STM32中Hz和時間的轉換

目錄 一、常見的頻率單位及其轉換 二、計算公式 三、STM32中定時器的應用 四、例子 一、常見的頻率單位及其轉換 赫茲&#xff08;Hz&#xff09;是頻率的國際單位&#xff0c;表示每秒鐘周期性事件發生的次數。 1 kHz&#xff08;千赫茲&#xff09; 1,000 Hz1 MHz&#…

《分布式軟總線:不同頻段Wi-Fi環境下設備發現兼容性難題》

分布式軟總線技術作為實現設備互聯互通的關鍵&#xff0c;正逐漸成為構建萬物互聯世界的基石。然而&#xff0c;當分布式軟總線面臨不同頻段Wi-Fi環境時&#xff0c;設備發現的兼容性問題成為了阻礙其廣泛應用的一大挑戰。這一問題不僅影響著用戶體驗&#xff0c;也制約著分布式…

MCP(Model Context Protocol 模型上下文協議)科普

MCP&#xff08;Model Context Protocol&#xff0c;模型上下文協議&#xff09;是由人工智能公司 Anthropic 于 2024年11月 推出的開放標準協議&#xff0c;旨在為大型語言模型&#xff08;LLM&#xff09;與外部數據源、工具及服務提供標準化連接&#xff0c;從而提升AI在實際…

【mongodb】數據庫操作

目錄 1. 查看所有數據庫2. 切換到指定數據庫&#xff08;若數據庫不存在&#xff0c;則創建&#xff09;3. 查看當前使用的數據庫4. 刪除當前數據庫5.默認數據庫 1. 查看所有數據庫 1.show dbs2.show databases 2. 切換到指定數據庫&#xff08;若數據庫不存在&#xff0c;則…

ICPR-2025 | 讓機器人在未知環境中 “聽懂” 指令精準導航!VLTNet:基于視覺語言推理的零樣本目標導航

作者&#xff1a;Congcong Wen, Yisiyuan Huang, Hao Huang ,Yanjia Huang, Shuaihang Yuan, YuHao, HuiLin and Yi Fang 單位&#xff1a;紐約大學阿布扎比分校具身人工智能與機器人實驗室&#xff0c;紐約大學阿布扎比分校人工智能與機器人中心&#xff0c;紐約大學坦登工程…

基于DeepSeek的考研暑假日志分析

注&#xff1a;我去年考研時寫了日志&#xff0c;大致記錄了我每天的主要活動。由于過于瑣碎&#xff0c;一直沒有翻看。突發奇想&#xff0c;現在利用deepseek總結其中規律。 從你的日志中可以總結出以下規律和活動興衰起落&#xff1a; ??一、學習活動規律與演變?? ??…

【刷題Day20】TCP和UDP

TCP 和 UDP 有什么區別&#xff1f; TCP提供了可靠、面向連接的傳輸&#xff0c;適用于需要數據完整性和順序的場景。 UDP提供了更輕量、面向報文的傳輸&#xff0c;適用于實時性要求高的場景。 特性TCPUDP連接方式面向連接無連接可靠性提供可靠性&#xff0c;保證數據按順序…

REST 架構詳解:從概念到應用的全面剖析

REST&#xff08;Representational State Transfer&#xff09;即表述性狀態轉移&#xff0c;是一種用于構建網絡應用程序的架構風格和設計理念&#xff0c;由計算機科學家羅伊?菲爾丁&#xff08;Roy Fielding&#xff09;在 2000 年提出。以下是關于它的詳細介紹&#xff1a…

藍橋杯之遞歸二

1.數的劃分 題目描述 將整數 nn 分成 kk 份&#xff0c;且每份不能為空&#xff0c;任意兩份不能相同(不考慮順序)。 例如&#xff1a;n7&#xff0c;k3n7&#xff0c;k3&#xff0c;下面三種分法被認為是相同的。 1&#xff0c;1&#xff0c;5;1&#xff0c;5&#xff0c;…