Redis常用命令及常见问题

405 阅读6分钟

Redis

五种数据结构

  • String字符串
  • hash哈希
  • list列表
  • set集合
  • zset有序集合

String

存储对象
  • SET KEY Value(json格式数据)
    
  • MSET user:1:name "XXX" user:1:age 25
    MGET user:1:name user:1:age
    
计数器

INCR KEY

Hash(KEY-VALUE)

对象缓存
  • HMSET KEY Field-Value [Field-Value...]
    HMGET KEY Field [Field....]
    
购物车
  • 添加商品

    HSET KEY Field Value#存储键值
    HSET car:userId productId num
    
  • 增加数量

HINCRBY KEY Field num#为field的值加上num
HINCRBY ar:userId productId num
  • 查询商品总数

    HLEN KEY#返回key中field数量
    HLEN car:userId
    
  • 删除商品

    HDEL KEY Field#删除指定field
    HDEL car:userId productId
    
  • 获取所有商品

    HGETALL KEY#返回key中所有键值
    HGETALL car:userId
    
优点
  • 同类数据归类整合储存,方便数据管理
  • 相比string操作消耗内存与cpu更小
  • 相比string储存更节省空间
缺点
  • 过期功能不能使用在field上,只能用在key
  • Redis集群架构下不适合大规模使用

List

常用数据结构
  • Stack(栈):LPUSH+LPOP ->FILO 左加+左取。 先进来的元素最后才能拿到
  • Queue(队列):LPUSH+RPOP。 左加+右取。 先进先出
  • Blocking MQ(阻塞队列):LPUSH+BRPOP。
消息流
  • 放消息

LPUSH KEY Value LPUSH msg:1888 10088


- 取消息

```shell
LRANGE KEY 开始位置 结束为止
LRANGE msg:1888 0 5

Set

抽奖(举例)
  • 点击参与抽奖加入集合

    SADD KEY Value#添加元素
    
  • 查看参与抽奖所有用户

    SMEMBERS KEY#获取key中所有元素
    
  • 筹集count名中奖者

    SRANDMEMBER KEY [COUNT] # 从集合中随机选出count元素,元素不从key中删除
    SPOP KEY [COUNT]#从集合中随机选出count元素,元素不从key中删除
    
点赞
  • 点赞
    SADD KEY Value#添加元素
    
  • 取消点赞
    SREM KEY Value#删除元素
    
  • 检查用户是否点赞 ```shell SISMEMBER KEY Value#判断value是否存在与key中
  • 获取点赞的用户列表
    SMEMBERS KEY #获取key中所有元素
    
  • 获取点赞用户数
    SCARD KEY e#获取元素个数
    
集合操作
  • 交集

    SINTER KEY1 KEY2 KEY3 ...
    
  • 并集

    SUNION KEY1 KEY2....
    
  • 差集(以第一个集合为准,后面所有集合的并集)

    SDIFF KEY1 KEY2 ....
    
缓存雪崩

指缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉

解决方法
  • 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
  • 一般并发量不是特别多的时候,使用最多的解决方案是加锁排队
  • 给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存
缓存穿透

指缓存和数据库中都没有的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉

解决方法
  • 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截
  • 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
  • 采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对底层存储系统的查询压力
缓存击穿

指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。和缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库

解决方法
  • 设置热点数据永远不过期
  • 加互斥锁,互斥锁
缓存预热

就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!

缓存更新
  • 先删缓存,再更新数据库
  • 先更新数据库,再删缓存
  • 先更新数据库,再更新缓存
  • read/write through
  • 写回,在更新数据的时候,只更新缓存,不更新数据库,而我们的缓存会异步地批量更新数据库
缓存降级

当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级

缓存淘汰策略
  • 当内存不足以容纳新写入数据时,新写入操作会报错。
  • 当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key
  • 当内存不足以容纳新写入数据时,在键空间中,随机移除某个key
  • 当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key
  • 当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key
  • 当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除
哨兵机制

哨兵是 redis 集群机构中非常重要的一个组件,主要有以下功能:

  • 集群监控:负责监控 redis master 和 slave 进程是否正常工作。
  • 消息通知:如果某个 redis 实例有故障,那么哨兵负责发送消息作为报警通知给管理员。
  • 故障转移:如果 master node 挂掉了,会自动转移到 slave node 上。
  • 配置中心:如果故障转移发生了,通知 client 客户端新的 master 地址。
分布式锁

synchronized重锁针对的是单个JVM,若项目复制在多台tomcat下,也会出现相同操作。解决这样的办法就是使用分布式锁,因为redis是单线程处理程序。

setnx:只有key不存在才会进行set,若存在则不做任何操作

程序问题
  • 若抢到锁的线程抛出异常:将业务代码用try-finally,在finally中释放锁
  • 抢到锁的服务宕机:设置超时时间
  • 在高并发情况下,业务执行时间大于超时时间,导致后来的线程获得锁,前者线程执行完释放了后来的锁:自己释放自己的锁,加个标识,开个小线程给锁续命。

Redisson