Backend Development 13 min read

Design and Implementation of QQ Reminder Subscription Push System

This article details the architecture, technical requirements, and implementation techniques—including hybrid push‑pull, heterogeneous storage, distributed scheduling, task chunking, and at‑least‑once delivery—used to build a high‑concurrency, reliable reminder notification service for QQ.

Architect
Architect
Architect
Design and Implementation of QQ Reminder Subscription Push System

QQ serves a massive mobile user base, and its reminder subscription feature is critical for both users and business partners, requiring high reliability, controllable rate, and efficient delivery.

The solution adopts a Dispatcher + Worker model with a hybrid push‑pull mechanism: tasks are pre‑downloaded to clients at 00:00 (pull) while remaining notifications are pushed, ensuring timely reminders and preventing last‑minute modifications.

Data is stored heterogeneously: task metadata resides in MySQL for durability, while the massive subscription list (user UINs) is kept in Redis sets for fast read/write, leveraging Redis's single‑threaded model, set‑based de‑duplication, and efficient bulk spop operations.

To guarantee timely execution, a distributed timer based on Redis sorted sets handles delayed tasks, complemented by a local database poller that retries after a 3‑second fallback, ensuring idempotent execution.

Controllable scheduling is achieved with a distributed rate limiter using Redis INCR to count per‑second dispatches; if the limit is exceeded, dispatchers wait for the next second. Pseudocode:

CREATE TABLE table_xxx(
    ds BIGINT COMMENT '数据日期',
    label_name STRING COMMENT '标签名称',
    label_id BIGINT COMMENT '标签id',
    appid STRING COMMENT '小程序appid',
    useruin BIGINT COMMENT 'useruin',
    tag_name STRING COMMENT 'tag名称',
    tag_id BIGINT COMMENT 'tag id',
    tag_value BIGINT COMMENT 'tag 权重值'
) PARTITION BY LIST(ds) SUBPARTITION BY LIST(label_name) (
    SUBPARTITION sp_xxx VALUES IN ('xxx'),
    SUBPARTITION sp_xxxx VALUES IN ('xxxx')
);

Large tasks are split into 5,000‑UIN chunks, allowing fine‑grained rate control; workers fetch each chunk via spop and push notifications concurrently.

A message queue decouples scheduling from execution, providing peak‑shaving, asynchronous processing, and at‑least‑once delivery guarantees.

For at‑least‑once push, a Redis Lua script atomically moves a batch of UINs from the subscription set to a task set, preserving the data if the push fails:

redis.replicate_commands()
local set_key, task_key = KEYS[1], KEYS[2]
local num = tonumber(ARGV[1])
local array = redis.call('SPOP', set_key, num)
if #array > 0 then
    redis.call('SADD', task_key, unpack(array))
end
return redis.call('SCARD', task_key)

Disaster recovery uses dual storage: each subscription event is recorded in Tencent's CKV KV‑store and mirrored in a Redis cluster (2 replicas, 3 shards), enabling recovery from either source.

Overall, the Dispatcher + Worker architecture, combined with hybrid push‑pull, heterogeneous storage, distributed rate limiting, task chunking, and reliable messaging, delivers a scalable, controllable, and fault‑tolerant push notification service for QQ.

push notificationsdistributed schedulingRedishigh concurrencyMySQLMessage Queue
Architect
Written by

Architect

Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.

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.