使用 Redis 的 sorted set 實現用戶排行榜


要求:實現一個用戶排行榜,用戶數量有很多,排行榜存儲的是用戶玩游戲的分數,對排行榜的讀取壓力比較大,如何實現?

思路分析:

  1. 實現排行榜,可以考慮使用 Redis 的 zset 結構;
  2. 用戶數量很多的話,需要了解 zset 最多能存儲多少元素;
  3. zset 中的 value 使用用戶的 user_id,score 就是用戶游戲的得分;
  4. 讀取壓力大,可以考慮讀寫分離,master 上寫用戶的分數,多個 slave 上讀取數據,用來展示;
  5. 如果存在多個 slave,怎么實現負載均衡,避免所有的流量都打到一個從庫上呢?

實現

1. zset 最多能存儲多少元素?

The max number of members in a set is 232 - 1 (4294967295, more than 4 billion of members per set).
Redis Sorted Sets are, similarly to Redis Sets, non repeating collections of Strings.
所以 Redis 的有序集合一般情況下完全夠用了。

2. 如何使用 zset 更新用戶數據,獲取用戶分數和排名,獲取排行榜前 100 名;

# 更新用戶數據
def update_user_data(user_id, score):
	redis_key = 'RANKING'
    master_redis.zadd(redis_key, score, user_id)  # 對 master 進行寫入操作

# 獲取用戶分數和排名
def get_user_ranking(user_id):
    redis_key = 'RANKING'
    with slave_redis.pipeline() as pipeline:
        pipeline.zscore(redis_key, member_id)
        pipeline.zrevrank(redis_key, member_id)
        results = pipeline.execute()
        score = results[0] or 0
        ranking = results[1]
    return {
        'score': int(score),
        'ranking': ranking+1 if ranking is not None else None
    }

# 獲取某個區間的用戶排行
def get_rankings(start=0, end=100):
	redis_key = 'RANKING'
	return [{'user_id': item[0], 'score': item[1]} for item in slave_redis.zrevrange(redis_key, start, end, withscores=True, score_cast_func=int)]

3. 怎么實現負載均衡?

用戶游戲的排行榜讀多寫少,可以對 master 進行寫入操作,然后多個 slave 進行讀取操作。

import random
from redis import StrictRedis

master_redis = StrictRedis.from_url(conf['redis']['master'])
slave_redis = StrictRedis.from_url(random.choice(conf['slaves'))


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM