Backend Development 11 min read

Implementing a Real‑Time Leaderboard with Redis and PHP

This article explains how to build a real‑time game leaderboard using Redis sorted sets, covering ranking categories, composite scoring formulas, dynamic updates, efficient data retrieval with pipelines, and provides a complete PHP class implementation.

IT Xianyu
IT Xianyu
IT Xianyu
Implementing a Real‑Time Leaderboard with Redis and PHP

1. Introduction

Recently a real‑time leaderboard was added to a mobile tank game, featuring global ranking, individual player lookup, and dual‑dimension sorting. The data volume ranges from 10,000 to 500,000 entries.

2. Leaderboard Categories

Rankings are divided by entity type:

Characters

Guilds (Clans)

Tanks

The game includes multiple tank types (light, heavy, etc.) and allows players to join a guild.

Each category can be further refined, for example:

- Combat Power Ranking (1. Combat 2. Level)
- Personal Arena Ranking (1. Arena Rank)
- Tower Ranking (1. Floor 2. Completion Time)
- Prestige Ranking (1. Prestige Value 2. Level)
- Guild Level Ranking (1. Guild Level 2. Total Combat Power)
- Tank Rankings: Medium, Heavy, AT‑Gun, Self‑Propelled Artillery
Values in parentheses indicate sorting dimensions.

3. Design Idea

Because of the real‑time requirement, Redis is chosen to implement the leaderboard. The article references the Redis online manual for command details.

Key problems to solve:

Composite (two‑dimensional) sorting

Dynamic updates of ranking data

Efficient retrieval of the leaderboard

4. Implementing Composite Sorting

Redis Sorted Sets (ZSET) are used. Adding a member with a score is done via ZADD key score member [score member] ... . By default, equal scores are ordered by member name.

4.1 Level Ranking

Score is calculated as Score = Level * 10000000000 + CombatPower . Levels range from 1‑100 and combat power up to 100,000,000, fitting comfortably within Redis 64‑bit integer limits.

4.2 Tower Ranking

Ranking by floor number and earlier completion time uses the formula Score = Floor * 10^N + (ReferenceTime - CompletionTimestamp) , with a far future reference time (e.g., 2050‑01‑01 00:00:00, timestamp 2524579200) and N=10 to keep ten digits for the relative time.

4.3 Tank Ranking

Tank rankings use a composite member ID formed by uid_tankId , which must be handled carefully.

5. Dynamic Data Updates

Only the UID is stored in the sorted set; dynamic player data (name, avatar, guild, VIP level, etc.) is kept in a Redis hash as a JSON string. When a player's level or combat power changes, the ZSET score is updated, and when display data changes, the hash entry is modified.

-- s1:rank:user:lv ---------- zset --
| playerId1 | score1
| ...
| playerIdN | scoreN
-------------------------------------
-- s1:rank:user:lv:item ------- string --
| playerId1 | player JSON data
| ...
| playerIdN | 
-----------------------------------------

Updating a player's score and data is done via a Redis pipeline to minimize round‑trips.

6. Retrieving the Leaderboard

To get the top 100 players of the level ranking:

ZRANGE key start stop [WITHSCORES]

Steps:

Use zRange("s1:rank:user:lv", 0, 99) to obtain the top 100 UIDs.

For each UID, call hGet("s1:rank:user:lv:item", $uid) to fetch the JSON data.

Using a pipeline reduces the number of network calls from up to 101 to just 2, greatly improving performance.

7. Code Example (PHP)

// $redis
$redis->multi(Redis::PIPELINE);
foreach ($uids as $uid) {
    $redis->hGet($userDataKey, $uid);
}
$resp = $redis->exec(); // results returned as an array
redis = $redis;
        $this->rankKey = $rankKey;
        $this->rankItemKey = $rankItemKey;
        $this->sortFlag = SORT_DESC;
    }

    public function getRedis()
    {
        return $this->redis;
    }

    public function setRedis($redis)
    {
        $this->redis = $redis;
    }

    public function updateScore($uid, $score = null, $rankItem = null)
    {
        if (is_null($score) && is_null($rankItem)) {
            return;
        }
        $redis = $this->getRedis()->multi(Redis::PIPELINE);
        if (!is_null($score)) {
            $redis->zAdd($this->rankKey, $score, $uid);
        }
        if (!is_null($rankItem)) {
            $redis->hSet($this->rankItemKey, $uid, $rankItem);
        }
        $redis->exec();
    }

    public function getRank($uid)
    {
        $redis = $this->getRedis()->multi(Redis::PIPELINE);
        if ($this->sortFlag == SORT_DESC) {
            $redis->zRevRank($this->rankKey, $uid);
        } else {
            $redis->zRank($this->rankKey, $uid);
        }
        $redis->hGet($this->rankItemKey, $uid);
        list($rank, $rankItem) = $redis->exec();
        return [$rank === false ? -1 : $rank + 1, $rankItem];
    }

    public function del($uid)
    {
        $redis = $this->getRedis()->multi(Redis::PIPELINE);
        $redis->zRem($this->rankKey, $uid);
        $redis->hDel($this->rankItemKey, $uid);
        $redis->exec();
    }

    public function getList($topN, $withRankItem = false)
    {
        $redis = $this->getRedis();
        if ($this->sortFlag === SORT_DESC) {
            $list = $redis->zRevRange($this->rankKey, 0, $topN);
        } else {
            $list = $redis->zRange($this->rankKey, 0, $topN);
        }
        $rankItems = [];
        if (!empty($list) && $withRankItem) {
            $redis->multi(Redis::PIPELINE);
            foreach ($list as $uid) {
                $redis->hGet($this->rankItemKey, $uid);
            }
            $rankItems = $redis->exec();
        }
        return [$list, $rankItems];
    }

    public function flush()
    {
        $redis = $this->getRedis();
        $redis->del($this->rankKey, $this->rankItemKey);
    }
}
?>

This simple class demonstrates how to maintain a leaderboard, with score calculation handled externally.

backendreal-timeRedisPHPSortedSetpipelineleaderboard
IT Xianyu
Written by

IT Xianyu

We share common IT technologies (Java, Web, SQL, etc.) and practical applications of emerging software development techniques. New articles are posted daily. Follow IT Xianyu to stay ahead in tech. The IT Xianyu series is being regularly updated.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.