redis在一线互联网公司中的常用场景

前言
相信大家对redis都非常熟悉,它是一个非常高性能的单线程缓存数据库。但大家对它的每种数据结构十分都非常熟悉吗?还是仅仅停留在只使用它的string结构,把它当memcached来使用呢?其实善用它的每种数据结构的话,确实能给我们日常开发提供非常的便利,可以省下很多复杂的sql查询和逻辑代码。本文就结合自己多年的开发经验分别对redis每种数据结构以及在一线互联网公司的业务场景中的使用做一个总结。

redis常用的五种数据结构如下:

一. string

1.1 string字符串常用操作

原子加减

1.2 应用场景

1. 单值存储

SET key value
GET key

2. 对象缓存

1)SET user:1 value(json格式数据)

以上是我们通常使用的string存储方式,如果想在string中存储像map那样的数据结构行不行呢?一个小技巧就是对它的key用“:”隔开。

2)MSET user:1:name vonnwang user:1:age 18
MGET user:1:name user:1:age

3.分布式锁

我们利用redis去实现分布式锁的时候主要是利用SETNX命令写入一条数据,如果key不存在,第一次则写入成功;如果key已经存在,第二次写入失败。利用这个特性,我们在处理一些高并发分布式场景下的对商品库存进行减的操作。等执行完业务逻辑之后,再删除该key进行释放锁。

SETNX product:10001 true //第一次写入,返回1代表获取锁成功
SETNX product:10001 true //第二次写入,返回0代表获取锁失败

…执行业务操作
DEL product:10001 //执行完业务释放锁

SETNX product:10001 ex 10 nx //防止程序意外终止导致死锁

4. 计数器

比如我们通常在微信朋友圈看到某一篇文章阅读量的时候,需要对文章阅读次数做一个计数。

这时候就可以把文章id作为redis的key,通过INCR命令进行计数。
INCR article:readcount:{文章id}
GET article:readcount:{文章id}

5.web集群session共享

比如在做登录的时候,我们的项目通常部署在多台服务器上,并且搭建了负载均衡。用户第一次登录的时候被引导到了web1服务器,第二次登录被引导到web2服务器。如果我们在web1和web2服务器之后加一层redis,用来存储用户的sessionid。那么用户第一次通过web1服务器登录的时候把sessionid写入到redis,第二次通过web2再访问的时候就不需要再次登录了,以此实现了共享session的效果。

6.分布式系统全局id

当我们有几千万个用户,并且想给每个用户注册的时候给他分配个唯一的用户id的时候,这时候我们就不能把几千万的用户存在一张表里,需要分多个库,多张表存储。当我们对mysql进行分库分表的时候,我们的主见id就不能设置成自增。如果设置成自增的话,那table01和table02就会存在相同的主键id,这显然是不行的。我们就可以通过在redis中先批量生成一批用户id,注册的时候来一个就分配一个。

二. Hash结构

2.1 Hash常用操作

2.2 Hash应用场景
1.对象缓存

HMESET user {userid}:name vonnwang {userId}:age 18
HMESET user 1001:name vonnwang 1001:age 18
HMGET user 1001:name 1001:age

2.电商购物车

1)以用户id为key
2)以商品id为field
3)商品数量为value

购物车操作
1)添加商品 hset cart:用户id 商品id 商品数量
hset cart:1001 10011 1

2) 增加商品数量 hincrby cart:用户id 商品id 商品数量
hincrby cart:1001 10011 1

3)某个用户购物车商品总数量
hlen cart:1001

4)删除商品 hdel cart:用户id 商品id
hdel cart:1001 10011

5)获取购物车所有商品 hgetall cart:1001
hgetall cart:1001

由此可见,如果通过redis去实现的话非常方便,要是写sql语句或者业务逻辑代码实现不仅性能低而且复杂。

优点:
1)同类数据归类整合存储,方便数据管理
2)相比string操作消耗内存与cpu更小
3)相比string存储更节省空间

缺点
1)过期功能不能使用在field上,只能用在key上
2)redis集群架构下不适合大规模使用。比如下图某个key有几百万条数据,那key经过hash计算之后只能落在同一个服务器节点为0,那该key的几百万条数据只落在master为0的节点机器上,不利于实现负载均衡。

三. List结构

3.1 List常用操作

LPUSH key value [value …] //将一个或多个值value插入到key列表的表头(最左边)
RPUSH key value [value …] 将一个或多个值value插入到key列表的表尾(最右边)
LPOP key //移除并返回key列表的头元素
RPOP key //移除并返回列表的尾元素
LRANGE key start stop //返回列表key中指定区间的元素,区间以偏移量start和stop指定

BLPOP key [key…] timeout //从key列表表头弹出一个元素,若列表中没有元素,阻塞等待
BRPOP key [key…] timeout //从key列表表尾弹出一个元素,若列表中没有元素,阻塞等待timeout秒,如果timeout=0一直阻塞等待

3.2 List应用场景

stack(栈) = LPUSH + LPOP -> FILO
Queue(队列) = LPUSH + RPOP
BlockingMq(阻塞队列) = LPUSH + BRPOP

1.微博和微信公众号消息流

微博消息或微信公众号消息
vonnwang关注了罗永浩,infoQ等大V
1)罗永浩发微博,消息id为10018
LPUSH msg:{vonnwang-ID} 10018

2)infoQ发微博,消息id为10086
LPUSH msg:{vonnwang-ID} 10086

3)查看最新消息
LRANGE msg:{vonnwang-ID} 0 10

四. Set集合

4.1 Set常用操作

4.2 set运算操作

4.3 set应用场景

1.微信微博点赞,收藏,标签

1)点赞
SADD like:{消息id} {用户id}

2)取消点赞
SREM like:{消息id} {用户id}

3)检查用户是否点过赞
SISMEMBER like:{消息id} {用户id}

4)获取点赞的用户列表
SISMEMBER like:{消息id}

5)获取点赞用户数
SCARD like:{消息id}

2)微信抽奖小程序

1)点击参与抽奖加入集合
SADD key {userID}

2)查看参与抽奖的所有用户
SMEMBERS key

3)抽取count名中奖者
SRANDMEMBER key [count] /SPOP key [count]

3)查看共同好友,可能认识的人

五. 有序集合

5.1 Set常用操作
5.2 应用场景

1)游戏中的排行榜等

发表评论

电子邮件地址不会被公开。 必填项已用*标注