Implementing Online User Counting with Redis Sorted Sets (zset)
This article explains how to track online users by assigning each user a unique identifier, storing it in a Redis sorted set with an expiration timestamp, and using zadd, zrangeByScore, zremrangeByScore, and zrem commands together with browser fingerprinting to reliably count and clean up active sessions.
Hello! I'm sum Mo, a frontline developer who enjoys researching and documenting technical topics. This article describes a common online user counting feature implemented with Redis sorted sets (zset) and outlines the core Redis commands used.
1. Determining whether a user is online – For authenticated sites, the validity of a user token can be used; for public sites, techniques such as IP, deviceId, or browser fingerprinting are employed. Browser fingerprinting (e.g., using FingerprintJS or ClientJS) collects data like User-Agent, headers, screen resolution, timezone, language, and plugins to generate a unique ID.
// Install
npm install @fingerprintjs/fingerprintjs
// Usage example
import FingerprintJS from '@fingerprintjs/fingerprintjs';
FingerprintJS.load().then(fp => {
// Get visitor ID
fp.get().then(result => {
const visitorId = result.visitorId;
console.log(visitorId);
});
});The generated visitor ID is sent to the backend (via cookie or header) and used as the member in the Redis sorted set.
2. Adding online users with zadd
zadd takes a key, a score, and one or more members. Example: ZADD myzset 1 "one"
When a user logs in, we calculate an expiration timestamp and add the token to the sorted set:
// Set expiration time for the user token
LocalDateTime expireTime = LocalDateTime.now().plusSeconds(expireTimeout);
String expireTimeStr = DateUtil.formatFullTime(expireTime);
// Add token to sorted set
redisService.zadd("user.active", Double.parseDouble(expireTimeStr), userToken);Because a user may log in multiple times, the same token could be added repeatedly; using the expiration timestamp as the score ensures only the latest login is kept.
3. Querying online users with zrangeByScore
zrangeByScore retrieves members whose scores fall within a given range. Example: ZRANGEBYSCORE myzset 1 3
To get all currently online users we query from the current time to +inf :
// Get current timestamp
String now = DateUtil.formatFullTime(LocalDateTime.now());
// Retrieve all users with score >= now
Set
userOnlineStringSet = redisService.zrangeByScore("user.active", now, "+inf");The size of userOnlineStringSet represents the number of online users.
4. Periodic cleanup with zremrangeByScore
zremrangeByScore removes members whose scores fall within a range. Example: ZREMRANGEBYSCORE myzset 1 3
A scheduled task removes entries whose expiration time is earlier than the current time:
// Get current timestamp
String now = DateUtil.formatFullTime(LocalDateTime.now());
// Remove all members with score <= now
redisService.zremrangeByScore("user.active", "-inf", now);This ensures that offline users are automatically purged from the set.
5. Removing a user on logout with zrem
zrem deletes specific members from a sorted set. Example: ZREM myzset "xxx"
// Delete a specific member (e.g., when the user logs out)
redisService.zrem("user.active", "xxx");Removing the member guarantees that a voluntarily logged‑out user is no longer counted as online.
Conclusion – By creating a Redis sorted set where the key is the online‑user collection, the member is the user identifier, and the score is the expiration timestamp, we can efficiently add, query, and clean up online user data with a few simple Redis commands.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.