Redis使用场景(一)
一、分布式锁:
场景:销售电影票(一个商品只能卖一个人)。
流程:
流程制定:看票》买票》将座位号做为key 用户名作为value 存入redis》交钱》改各种状态》清缓存
应该注意:1.问题:用户还没走到清缓存这一步就退出 会导致缓存一直存在。
解决:redis要设置过期时间 set expire 300(单位是s)。
2.问题:两个用户同时买票 会同时存redis 因为是同一个key所以不管是谁顶掉了谁的购买都是问题。
解决:redis有一个setnx指令 作用是:判断这个key是否已经有值,如果没有值,则设置这样的key-value,并返回1,如果有值则不设置,直接返回0。
example:1:成功 0:失败
这样就防止后来的把先来的顶掉。
二、防止超卖
场景:5w个人一起抢10个商品。
流程:每个人读取库存数,且用行锁控制。
问题:这样会极其影象速度是不可取的,应该用redis代替行锁:
1.创建秒杀商品A时,创建redis对象:set A 10 , 创建数据库对象:A 10。
2.当用户秒杀时调用 redis:INCRBY A -1 并且在redis添加购买人与购买时间:hset : A p1 1478584205( hset 商品名 购买人 购买时间)
redis知识点:incrby: 将key 中储存的数量指定增量之值,如果key不存在初始值默认为0 .
hset: 为hash表中的字段赋值,如果hash表不存在 新建hash表并赋值,如果hash表已存在,用新值覆盖旧值。example:
如果字段是哈希表中新建字段,并且值设置成功,返回 1 。 如果哈希表中字段已经存在且旧值已被新值覆盖,返回 0 。
3.如果get A<0 ,则提示商品以售罄。
4.用户付款后 扣除数据库中秒杀库存 并且 删除 redis hdel A p1。
redis知识点:hdel 删除redis hash表中一个或多个字段。example: 1:成功 0:失败
5.跑定时看下单但未付款的人 ,超过一定时间归还redis库存:incrby A 1。
三、对象关系存储
场景:客服系统会用websocket进行通讯,所以可能发生断网,掉线的情况,但是要求客服和用户登陆状态是实时监控的,并且将用户快速分配给客服。
redis主要记录用户信息,客服信息,两者关系:用户-客服 一对一 ,客服对用户 一对多。主要使用redis的 hash结构和set结构。
流程:
场景1:客服登录:认证客服登录(OAuth认证)
》将客服基本信息存入redis:
hset customer1 nickname kf1 (key:customer1(客服唯一标识 ) 客服名字:kf1)
hset customer1 status 1(key:customer1(客服唯一标识 ) 登陆状态:1)
》将登陆后的客服存入redis中:
sadd kf customer1
知识点:sadd将一个或多个成员元素加入到集合中 example:
注意:客服退出后可使用smove kf customer1,客户掉线的话还可以恢复。
场景2:用户登录(通过userid登录:用户唯一标识)》获取用户信息存入redis
hset normaluser1 nickname user1(normaluser1 (用户唯一标识 ) 用户名字:user1)
hset normaluser1 status 1(key:customer1(客服唯一标识 ) 登陆状态:1)
hset normaluser1 customerid customer1(存放用户对应客服)
》存放客服对应客户关系(一对多):
hset customer1 normaluser1 1234(关联关系id)
场景3:业务需求:
1.查询在线客服:smembers kf 获得客服唯一标识再获取具体信息
知识点:smembers 返回集合所有成员。example:
2.获取某客服下所有用户 hkeys coustomer1
知识点:hkeys 获取哈希表中所有域.。example:
3.获取用户对应的客服 hget customer1 normaluser1
知识点:hget 返回hash表指定字段值。example:
4.客服进行转接操作 :
hset normaluser1 customid customer2 #给用户赋予新的客服
hdel cusomer1 normaluser1 #删除客服1哈希表中用户1
hset customer2 normaluser1 3412(关系标识) #赋予客服2哈希表用户1