惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
爱范儿
爱范儿
J
Java Code Geeks
L
LangChain Blog
V
V2EX
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
博客园 - Franky
Microsoft Azure Blog
Microsoft Azure Blog
Jina AI
Jina AI
Blog — PlanetScale
Blog — PlanetScale
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The Cloudflare Blog
博客园 - 司徒正美
B
Blog
G
Google Developers Blog
Stack Overflow Blog
Stack Overflow Blog
罗磊的独立博客
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Apple Machine Learning Research
Apple Machine Learning Research
Engineering at Meta
Engineering at Meta
MyScale Blog
MyScale Blog
有赞技术团队
有赞技术团队
Hugging Face - Blog
Hugging Face - Blog

星辰日记

临时邮箱:开发者的隐私工具实践笔记 为 QuMagie 备份的照片添加 Exif 信息 Riverpod - flutter 状态管理的应用 夜景随拍 大疆 Mini 4K 初体验 5月12日 随笔 你好 2024 HHKB 使用体验 历经59天, 终于拿到软著 渺软公益CDN - 又一个静态资源加速站 你好 2023 记一次 RAID 硬盘离线 大一 碎语 试用 Google CA 的 SSL 证书 Waline 邮件异步推送 Magic Trackpad 使用体验 Centos 编译安装 php81 Centos 7 升级 Glibc-2.28 Nginx 重写 Query 参数
Redis 统计实时在线人数
xcsoft · 2022-06-06 · via 星辰日记

zset

Redis 中的 sorted set (有序集合) 也称为 zset. 它提供了两个参数, 一个为 score, 一个为 member.

其中, score 为排序的分数, 它可以是双精度或者整数. 其结构类似

1
2
3
        | (score) member1
key => | (score) member2
| (score) member3

如何实现

我们可以简单的通过 zadd 方法向一个有序集合内添加成员.

为了方便演示, 在这里使用 Interval 的方式, 定时请求指定接口. 将 score 设置为请求时的 unix时间戳

zset 提供了一个 zcount 方法, 可以让我们快速获取指定 socre 范围内的成员数量.

我们假设用户5秒钟内无操作, 即掉线. 这样便可以通过 zcount 获取实时在线人数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
func main() {

r := gin.Default()

r.GET("/", func(c *gin.Context) {
_redis := redisutil.R.Get()
defer redis.Close()


userId := c.ClientIp()
_, _ = _redis.Do("ZADD", "online_user", time.Now().Unix(), userId)


count, _ := redis.Int(_redis.Do("ZCOUNT", "online_user", time.Now().Unix()-5, "+inf"))

c.JSON(200, gin.H{
"count": count,
})
})

r.Run()
}

当然, 为了防止 数据一直增加, 对于 5秒前的数据, 应该定时将其移出.

我们可以通过 zremrangebyscore 方法, 来移除 指定范围内的数据.

1
2
3
4
5
6
7
8
9
10
11
func AutoRemover() {
_redis := redisutil.R.Get()
defer redis.Close()

c := Cron.New()

c.AddFunc("@every 5s", func() {
_, _ = _redis.Do("ZREMRANGEBYSCORE", "online_user", "-inf", time.Now().Unix()-5)
})
c.Start()
}

zset 的其他方法

除了上述提到的方法, zset 还提供了很多其他的方法, 如:

  • zcard key 直接获取 指定 key 内的成员数量
  • zscore key member 获取指定成员的分数
  • zincrby key incr member 增加指定成员的分数
  • zrange key start end [WITHSCORES] 获取指定范围内的成员 并按照分数从小到大排序
  • zrevrange key start end [WITHSCORES] 与上一个相反
  • etc.

其他

可以在 Github 找到 示例.

这里同时实现了, 所有用户及自己的 在线时间显示.

当然, 也可以通过 WebSocket 来实现类似的功能, 这样会更加准确, 但是可能会带来一定的性能损失.

参考