71.工作中redis的常用场景总结

文章目录

  • 一、简介
  • 二、统计访问次数
  • 三、缓存
  • 四、分布式锁
  • 五、限流
  • 六、排行榜
  • 七、作为Session的存储器,存用户登录状态
  • 八、位统计
  • 九、生成全局ID

一、简介

Redis作为一种优秀的基于key/value的缓存,有非常不错的性能和稳定性,无论是在工作中,还是面试中,都经常会出现。

陆陆续续也写了一些Go操作redis以及redis使用场景的案例了,本文就记录一下工作中Redis常用的一些场景,做一个小结。

20. go-redis基本使用
70.Redis缓存优化实践(基于分类树场景)

二、统计访问次数

对于很多官方网站的首页,经常会有一些统计首页访问次数的需求。访问次数只有一个字段,如果保存到数据库中,再最后做汇总显然有些麻烦。

该业务场景可以使用Redis,定义一个key,比如:OFFICIAL_INDEX_VISIT_COUNT

在Redis中有incr命令,可以实现给value值加1操作:

incr OFFICIAL_INDEX_VISIT_COUNT

当然如果你想一次加的值大于1,可以用incrby命令,例如:

incrby OFFICIAL_INDEX_VISIT_COUNT 5

这样可以一次性加5

该场景下需要注意:68. redis计数与限流中incr+expire的坑以及解决办法(Lua+TTL)

三、缓存

Redis 的最常用的用例是缓存,以加快网络应用的速度。在这种用例中,Redis 将经常请求的数据存储在内存中。它允许网络服务器频繁访问的数据。这就减少了数据库的负载,并缩短应用程序的响应时间。在大规模应用中,缓存分布在 Redis 服务器集群中。
71.工作中redis的常用场景总结_第1张图片

Redis 作为分布式缓存时需要考虑的其他问题包括:

  • 设置正确的 TTL (Time to Live)
  • 处理冷启动时对数据库的密集访问
  • HotKey 、BigKey 29.Go处理Redis HotKey 以及30.Go处理Redis BigKey 以及69.使用Go标准库compress/gzip压缩数据存入Redis避免BigKey
  • 缓存击穿、雪崩、穿透等问题 49.Go避免大量并发访问DB、避免缓存击穿、缓存穿透、缓存雪崩以及使用延迟双删保证数据一致性
  • 延迟双删解决数据一致性问题

四、分布式锁

需要协调对某些共享资源的访问时,就会使用分布式锁。Redis 通过其原子命令(如 SETNX, SET if Not eXists)来做分布式锁。它允许调用者设置一个不存在的键。

比如,客户端通过设置一个唯一的 Key 来获取锁:

SETNX lock "1234abcd" EX 3

如果Key尚未设置,SETNX 命令返回 1,表明锁已被客户端获取。客户端完成工作后 删除 Key ,释放锁。

如果 Key 已被设置,SETNX 命令返回 0,表明锁已被其他客户机持有。在这种情况下,客户端会等待并重试 SETNX 操作,直到锁被其他客户端释放。

请注意,这种简单的实现对于许多用例来说已经足够好了,但并非完全容错。对于生产应用,许多 Redis 客户端库提供高质量的分布式锁实现。 聊聊redis分布式锁的8大坑

五、限流

使用Redis还有一个非常常用的的业务场景是做限流。当然还有其他的限流方式,比如:使用nginx,但使用Redis控制可以更精细。

比如:限制同一个ip1分钟之内只能访问10次接口,10分钟之内只能访问50次接口,1天之内只能访问100次接口。如果超过次数,则接口直接返回:请求太频繁了,请稍后重试。此时可以在Redis中保存用户的请求次数记录。

比如:key是用户ipvalue是访问的次数从1开始,后面每访问一次则加1。如果value超过一定的次数,则直接拦截这种异常的ip。当然也需要设置一个过期时间,异常ip如果超过这个过期时间,比如:1天,则恢复正常了,该ip可以再发起请求了。或者限制同一个用户id
26.redis实现日限流、周限流(含黑名单、白名单)
27.Go实现一月(30天)内不发送重复内容的站内信给用户
同样,该场景下涉及到计数incr,所以也需要注意:68. redis计数与限流中incr+expire的坑以及解决办法(Lua+TTL)

六、排行榜

很多网站有排行榜的功能,比如:商城中有商品销量的排行榜,游戏网站有玩家获得积分的排行榜。

通常情况下,我们可以使用Sorted Set保存排行榜的数据。

使用ZADD可以添加排行榜的数据,使用ZRANGE可以获取排行榜的数据。

例如:

ZADD rank:score 100 "周星驰"
ZADD rank:score 90 "周杰伦"
ZADD rank:score 80 "周润发"
ZRANGE rank:score 0 -1 WITHSCORES

返回数据:

 "周星驰"
 "100"
 "周杰伦"
 "90"
 "周润发"
 "80"

七、作为Session的存储器,存用户登录状态

另一个常见用例是将 Redis 用作 Session 存储,在无状态服务之间共享 Session 数据。

当用户登录网络应用程序时,服务端会创建一个唯一的 Session IDSession 数据会存储在 Redis 中,然后 Session 作为 Cookie 的一部分返回给客户端。

当用户向应用程序发出请求时,Session ID 会包含在请求中。无状态网络服务器会使用 Session 数据。值得注意的是 Redis 是内存数据库。如果 Redis 服务器重启,存储在 Redis 中的 Session 数据会丢失。

即使 Redis 提供了 RDBAOF 等持久化选项,但这些选项在重启时加载数据的时间往往太长,不实用。在实际生产环境中,数据会复制到备份实例。如果主实例崩溃,备份迅速升级,接管流量。

使用Redis保存用户登录状态,有个好处是它可以设置一个过期时间,比如:该时间可以设置成30分钟。

Redis内部有对应的策略,会将过期的数据删除,也有获取数据时才实时删除的逻辑。

八、位统计

比如现在有个需求:有个网站需要统计一周内连续登陆的用户,以及一个月内登陆过的用户。这个需求使用传统的数据库,实现起来比较麻烦,但使用Redisbitmap让我们可以实时的进行类似的统计。

bitmap 是二进制的byte数组,也可以简单理解成是一个普通字符串。它将二进制数据存储在byte数组中以达到存储数据的目的。

保存数据命令使用setbit,语法:

setbit key offset value

具体示例:

setbit user:view:2024-01-20 123456 1

bitmap数组中设置了用户id=123456的登录状态为1,标记2024-01-20已登录。

然后通过命令getbit获取数据,语法:

getbit key offset

具体示例:

getbit user:view:2024-01-17 123456

如果获取的值是1,说明这一天登录了。

如果我们想统计一周内连续登录的用户,只需要遍历用户id,根据日期中数组中去查询状态即可。

九、生成全局ID

在有些需要生成全局ID的业务场景,其实也可以使用Redis

可以使用incrby命令,利用原子性操作,可以执行下面这个命令:

incrby userid 10000

在分库分表的场景,对于有些批量操作,我们可以从Redis中,一次性拿一批id出来,然后给业务系统使用。

你可能感兴趣的:(go,redis,数据库,缓存)