Redis®*: 即時排名用戶
學習如何使用 Redis 即時為 200 萬用戶按分數排名
👋 歡迎來到 Stackhero 文件!
Stackhero 提供即用型的 Redis cloud 解決方案,帶來多項優勢,包括:
- 包含
Redis Commander網頁介面。- 無限制的訊息大小和傳輸。
- 只需點擊即可輕鬆完成 更新。
- 由 專用私有 VM 提供的最佳 效能和強大 安全性。
節省時間並簡化您的生活:只需 5 分鐘即可嘗試 Stackhero 的 Redis cloud hosting 解決方案!
我們的一位客戶提出了一個有趣的挑戰。他經營一個體育網站,當用戶贏得賭注或完成各種操作時,他們會獲得積分。
他的目標是顯示每個用戶的排名,展示他們上下的用戶,並生成前 100 名排行榜。擁有 200 萬用戶的社群,數據需要即時處理!
在 Stackhero,我們喜歡應對這樣的挑戰。在本文中,我們將逐步引導您了解我們的解決方案。
為什麼選擇 Redis
傳統數據庫如 MySQL、PostgreSQL 或 Elasticsearch 並非為低延遲排名任務設計。這促使我們探索其他選擇。
我們選擇了 Redis,這是一個極快且可靠的內存數據庫。根據 DB-Engines,它是全球第七大使用最廣泛的數據庫,也是 "Key-value store" 類別中的領先選擇。
Redis 提供多種數據模型。對於這個場景,一個模型脫穎而出:"sorted sets"。
技術驗證
Sorted sets 結合了鍵和分數。在我們的情況下,鍵是用戶 ID,分數代表用戶的積分。
我們開始啟動 Stackhero 上的 Redis 服務。該服務在 2 分鐘內即可啟動,提供最新穩定版本,按小時計費,並配有 Redis Commander,一個方便的網頁 GUI。我們使用此界面驗證了概念。
我們添加了三個用戶,示例 ID 和分數如下所示:
| 用戶名 | 分數 | | - | - | | userId1 | 11 | | userId2 | 54 | | userId3 | 24 |
這些用戶使用以下 Redis 命令添加到名為 usersScores 的 sorted set 中:
ZADD usersScores 11 "userId1"
ZADD usersScores 54 "userId2"
ZADD usersScores 24 "userId3"
Redis Commander,Stackhero 上提供的 Redis 實例的網頁 GUI
接下來,我們檢索 userId1 的分數:
ZSCORE usersScores "userId1"
> 11
這確認了 userId1 的分數確實是 11。之後,我們檢查了 userId1 的排名:
ZREVRANK usersScores "userId1"
> 2
請記住,排名從 0 開始。這意味著排名如下:
| 用戶名 | 分數 | 排名 | | - | - | - | | userId1 | 11 | 2 | | userId2 | 54 | 0 | | userId3 | 24 | 1 |
命令 ZREVRANK 返回了 2,這正是我們對 userId1 的預期。
您還可以獲取頂部條目。例如,要檢索前 2 名用戶(從排名 0 到排名 1),請運行:
ZREVRANGE usersScores 0 1 WITHSCORES
> 1) userId2
> 2) 54
> 3) userId3
> 4) 24
要獲取前 100 名用戶,只需運行:
ZREVRANGE usersScores 0 99 WITHSCORES
這種方法高效且非常適合高性能即時排名。
其他有用的命令
以下是我們客戶網站上使用的一些其他 Redis 命令:
- 獲取排名在 50 到 100 之間的用戶:
ZREVRANGE usersScores 50 100 WITHSCORES - 添加用戶:
ZADD usersScores 40 "userId4" - 更新用戶的分數(這將替換現有的
userId4條目):ZADD usersScores 42 "userId4" - 刪除用戶:
ZREM usersScores "userId4"
使用 Node.js 的 Redis 代碼示例
在 Redis Commander 中驗證概念後,是時候將 Redis 集成到實際代碼中了。我們的客戶使用 Node.js,以下是使用 ioredis 作為客戶端的示例:
const Redis = require('ioredis');
(async () => {
// 設置 Redis 憑證
// 如果您使用 Stackhero,您可以在 Stackhero 儀表板上找到這些
const redis = new Redis({
host: '<redisServerHost>',
password: '<redisServerPassword>',
port: <PORT_TLS>, // <PORT_CLEAR> 用於非加密連接,<PORT_TLS> 用於 TLS。應使用 TLS。
tls: {}, // 提供一個空對象以啟用 TLS
lazyConnect: true
});
// 連接到 Redis
await redis.connect();
// 添加用戶
await redis.zadd('usersScores', 11, 'userId1');
await redis.zadd('usersScores', 54, 'userId2');
await redis.zadd('usersScores', 24, 'userId3');
// 檢索 userId1 的分數
const score = await redis.zscore('usersScores', 'userId1');
console.log('userId1 有 ' + score + ' 分');
// 檢索 userId1 的排名位置
const rankPosition = await redis.zrevrank('usersScores', 'userId1');
console.log('userId1 排名在位置 ' + rankPosition);
// 從 Redis 斷開連接
await redis.disconnect();
})();
這個簡單而強大的代碼片段非常適合管理即時排名數據。
結論
解決這個問題既有趣又具有挑戰性。對我們來說,Redis 被證明是一個理想的解決方案,因為它易於使用、功能強大且速度極快。
如果您想嘗試 Redis,您可以在 Stackhero 上在 2 分鐘內啟動一個實例。享受最新穩定版本、網頁 GUI、備份和令人印象深刻的性能,盡在指尖。
Stackhero 儀表板顯示正在運行的 Node.js 和 Redis 服務