Redis 的五种数据类型应用场景

摘要:redis 的五种数据类型应用场景,redis 的数据类型比较多,所以可以应用的场景也很多,比如缓存,共享 session,排行榜系统,计数器应用,社交网络,利用 hash 存储结构数据,用户和标签的关联,消息队列系统,分布式锁等。

Redis 使用场景前提

redis 快的原因是数据存在内存中的,没有磁盘的 i/o。但是内存要比磁盘要珍贵的很多,我们要根据业务场景的需要,合理的利用好内存。我们可以将一些频繁变更的数据放到 redis 中来加速读写,也可以减轻后端存储频繁更新操作的负担。

redis 的数据类型比较多,多种数据类型的应用场景也比较多,redis 可以多很多事情,比如:缓存、排行榜系统、计数器应用、社交网络、消息队列系统、分布式锁等。

其实没有规定说,那种数据类型就必须使用那种场景,只是这种数据类型可能更加适合这个场景,以下是几种数据类型在业务中经常用到的场景。


String 数据类型使用场景

缓存

redis 作为缓存,这种是最常用的场景了。作为 key => value,redis 最基础的就是和 memcache 一样缓存数据了,不过 redis 不像 memcache 一样可以直接存数组,需要将数据序列化后存储起来,然后下次访问的时候可以先访问缓存,缓存中没有再去访问数据库。

比如利用 php 的 serialize 序列化函数序 列化后存储起来,然后取出后再利用 php 的 unserialize 函数反序列化后使用。或者利用 php 的 json_encode 和 json_decode 也可以。

共享 session

现在一般生产环境服务器都是多台服务器,比如负载均衡架构。用户的请求会随机分配到某个服务器,会导致用户在 A 服务器登录,访问 B 服务器出现未登录情况,我们可以利用 redis 对用户的 session 进行集中管理,将服务器 session 存储到 redis 中。直接修改 php 的配置文件 php.ini 可以配置 session 的存储方式即可。

验证码或者限制用户频繁访问

1、用户获取完手机号后,会有个倒计时的功能,然后我们把这个存储到 redis 中,因为客户端存储时间限制还是不安全的。

2、还可以限制用户用户获取验证码频率。

2、还可以限制用户频繁操等场景,比如限制用户 3 内只能点击一次。

计数器

比如我们要统计每天的注册量,我们可以使用 string 数据类型的 incr 命令做一个计数器。

// 定时任务
1、生成一个 key 名为 register_count_today 的计数器
2、每天 0 点把这个计数器清零,以便第二天继续使用。

// 业务程序
用户注册后利用 incr 命令使这个 key 增加 1。


Hash 数据类型使用场景

存储用户信息

利用 hash 数据类型,可以存储用户信息,和 mysql 相似,但是要比 mysql 更加的灵活,哈希类型是疏松的,而关系型数据库是结构化的,redis 相比 mysql 操作上更加的敏捷,没有字段类型的约束。

利用 hash 存储结构数据来说,要控制哈希在 ziplist 和 hashtable 两种内部编码的转换,hashtable 会消耗更多内存。

127.0.0.1:6379> hmset user_info id 111 user_name zhangsan age 2
OK
127.0.0.1:6379> hmset user_info id 222 user_name lisi age 3
OK
127.0.0.1:6379> hmset user_info id 333 user_name wangwu age 4
OK
127.0.0.1:6379> hgetall user_info
1) "id"
2) "333"
3) "user_name"
4) "wangwu"
5) "age"
6) "4"

微博点赞数,评论数,转发数,浏览量等统计

同时统计多个计数器的时候,我们可以使用 hash 的 hincrby 命令来统计,用文章的 id 来设置 key 名,然后用户操作对应的类型,就给对应的类型增加 1。然后每天晚上我们把这些数据存入数据库中,第二天把数据库中的数据查询出来 redis 里面的数据再展示给用户就可以了。

127.0.0.1:6379> hincrby wenzhang_1 like_number 1
(integer) 1
127.0.0.1:6379> hincrby wenzhang_1 like_number 1
(integer) 2
127.0.0.1:6379> hincrby wenzhang_1 comment_number 1
(integer) 1
127.0.0.1:6379> hincrby wenzhang_1 forward_number 1
(integer) 1
127.0.0.1:6379> hincrby wenzhang_1 view_number 1
(integer) 1
127.0.0.1:6379> hincrby wenzhang_1 view_number 1
(integer) 2
127.0.0.1:6379> hgetall wenzhang_1
1) "like_number"
2) "2"
3) "comment_number"
4) "1"
5) "forward_number"
6) "1"
7) "view_number"
8) "2"


List 数据类型使用场景

列表是一种比较灵活的数据结构,它可以充当栈和队列的角色,在实际开发上有很多应用场景,常用命令组合搭配如下。

lpush + lpop = 栈

lpush + rpop = 队列

lpush + ltrim = 有限集合

lpush + brpop = 消息队列

消息队列

redis 的 lpush 和 brpop 命令组合可以实现阻塞队列,生产者利用 lpush 命令从列表左端插入元素,多个消费者使用 brpop 命令阻塞式的“抢”列表尾部的元素,多个客户端保证了消费的负载均衡和高可用性。

最新的动态展示

比如要做一个最新的微博显示,我们要显示最新的 100 条微博数量,我们可以利用 list 队列来做做此功能。用户每次发一条微博,利用 lpush 将它放在一个 last_weibo 的 key 队列中,然后利用 lrange 取出当前最新的微博数量,这样每次每次最新的微博就会出现在最上面。

127.0.0.1:6379> lpush last_weibo '2019年10月29日14:04:14'
(integer) 1
127.0.0.1:6379> lpush last_weibo '2019年10月29日14:04:27'
(integer) 2
127.0.0.1:6379> lpush last_weibo '2019年10月29日14:04:39'
(integer) 3
127.0.0.1:6379> lpush last_weibo '2019年10月29日14:04:53'
(integer) 4
127.0.0.1:6379> lrange last_weibo 0 -1
1) "2019\xe5\xb9\xb410\xe6\x9c\x8829\xe6\x97\xa514:04:53"
2) "2019\xe5\xb9\xb410\xe6\x9c\x8829\xe6\x97\xa514:04:39"
3) "2019\xe5\xb9\xb410\xe6\x9c\x8829\xe6\x97\xa514:04:27"
4) "2019\xe5\xb9\xb410\xe6\x9c\x8829\xe6\x97\xa514:04:14"

秒杀 && 高并发场景

比如公司的秒杀活动,肯定是生产者的速度大于消费者的速度,一旦活动开始,流量会突然暴增,这时候服务器处理不过来,肯定会出现宕机的,我们可以使用 redis 的 list 的数据类型,来缓冲下用户的请求。因为 redis 的写入和读取的速度非常快,这样用户把订单写入到 redis 中,就可以给用户返回下单成功了。

1、假如目前有 1000 个商品在秒杀,用户点击抢购后,利用 lpush 命令,从左边插入到队列中一个订单,因为 lpush 命令返回的是当前队列中的数量,可以根据这个返回的数量来判断当前队列中是否超过秒杀的数量,插入成功后就给用户返回下单成功。

2、然后后台程序再利用 rpop 命令依次处理队列中的订单。

127.0.0.1:6379> lpush tmp_orders 111111
(integer) 1
127.0.0.1:6379> lpush tmp_orders 222222
(integer) 2
127.0.0.1:6379> lpush tmp_orders 333333
(integer) 3
127.0.0.1:6379> rpop tmp_orders
"111111"
127.0.0.1:6379> rpop tmp_orders
"222222"
127.0.0.1:6379> rpop tmp_orders
"333333"


Set 数据类型使用场景

集合类型的应用场景通常为以下几种

sadd = 标签

spop/srandmember = 生成随机数,比如抽奖

sadd + sinter = 社交需求

网站标签功能

集合典型的使用场景就是标签了,例如一个用户可能对娱乐、体育比较感兴趣,另一个用户可能对历史、新闻比较感兴趣,这些兴趣点就是标签。有了这些数据就可以得到喜欢同一个标签的人,以及用户的共同喜好的标签。

这些数据对于用户体验以及增强用户黏度比较重要。例如一个电子商务的网站会对不同标签的用户做不同类型的推荐,比如对数码产品比较感兴趣的人,在各个页面或者通过邮件的形式给他们推荐最新的数码产品,通常会为网站带来更多的利益。

# 给用户添加多个标签,获取用户共同喜好的标签
127.0.0.1:6379> sadd user:1:tags tag1 tag2 tag5
(integer) 3
127.0.0.1:6379> sadd user:2:tags tag2 tag3 tag5
(integer) 3
127.0.0.1:6379> sadd user:3:tags tag1 tag2 tag4
(integer) 3
127.0.0.1:6379> sinter user:1:tags user:2:tags
1) "tag5"
2) "tag2"

# 给标签添加用户,获取该标签有多少用户喜欢
127.0.0.1:6379> sadd tag1:users user:1 user:2 user:3
(integer) 3
127.0.0.1:6379> sadd tag2:users user:1 user:3
(integer) 2
127.0.0.1:6379> sadd tag3:users user:1 user:2
(integer) 2
127.0.0.1:6379> sinter tag1:users
1) "user:2"
2) "user:1"
3) "user:3"
127.0.0.1:6379> sinter tag2:users
1) "user:1"
2) "user:3"


Sorted Set 数据类型使用场景

发帖排行榜功能

比如现在应用需要做一个发帖排行榜的功能,我们可以利用 sorted set 数据类型的 zincrby 命令,每次用户发帖都会都会使用 zincrby 命令使用户 id 的帖子数量加 1,然后获取的时候利用有序集合的倒序排列就可以。

127.0.0.1:6379> zincrby post_leaderboard 1 111111
"1"
127.0.0.1:6379> zincrby post_leaderboard 1 111111
"2"
127.0.0.1:6379> zincrby post_leaderboard 1 111111
"3"
127.0.0.1:6379> zincrby post_leaderboard 1 222222
"1"
127.0.0.1:6379> zincrby post_leaderboard 1 222222
"2"
127.0.0.1:6379> zincrby post_leaderboard 1 333333
"1"
127.0.0.1:6379> zincrby post_leaderboard 1 333333
"2"
127.0.0.1:6379> zrevrange post_leaderboard 0 -1 WITHSCORES
1) "111111"
2) "3"
3) "333333"
4) "2"
5) "222222"
6) "2"

参考:

Redis应用场景

结束语:感谢您对本网站文章的浏览,欢迎您的分享和转载,但转载请说明文章出处。
Top