redis知识点整理(持续更新)

redis

一、redis支持的数据类型

string(字符串)

  • 描述:
    二进制安全,基本的常用的数据类型,大能存储 512MB
  • 基本用法:
    1、写入: SET key “value”
    2、读取: GET key
  • 使用场景:
    常用的kv存取

    hash(哈希)

  • 描述:
    是一个键值(key=>value)对集合,也就是一个key对应多个kv
  • 基本用法:
    1、写入:
    多个kv:HMSET hash_key field_key1 “val1” field_key2 “val2”
    一个kv:HSET hash_key field_key3 “val3”
    2、读取:
    HGET hash_key field_key1
  • 使用场景:
    例如存用户信息

    list(列表)

  • 描述:
    按照插入顺序排序,你可以添加一个元素到列表的头部(左边)或者尾部(右边),常用实现队列,一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)
  • 基本用法:
    1、头部插入:
    LPUSH listKey val1
    LPUSH listKey val2
    LPUSH listKey val3
    尾部取出:
    RPOP listKey //val3

2、尾部插入:
RPUSH listKey val1
RPUSH listKey val2
RPUSH listKey val3
头部取出:
RPOP listKey //val1

  • 使用场景:
    队列实现,消息队列,商品抢购等等需要有序排队的情况

    set(集合)

  • 描述:
    String 类型的无序集合。成员是唯一的,不能出现重复的数据。

  • 基本用法:
    1、写入:
    SADD set_key val1 [val…]
    SADD set_key val2 [val…]
    2、读取:
    SMEMBERS set_key //读所有合集中的成员
    SCARD set_key //获取集合的成员数
    SREM set_key val2 [val…] //移除集合中一个或多个成员

  • 使用场景:
    例如存一个人的粉丝,交集、并集、差集等操作,可以非常方便的实现如共同关注等功能

    zset(sorted set:有序集合)

  • 描述:
    String 类型的有序集合。不能出现重复的数据,每个元素都会关联一个 double 类型的分数(score),分数可重复

  • 常用命令:
    zadd(key, score, member):向名称为key的zset中添加元素member,score用于排序。如果该元素已经存在,则根据score更新该元素的顺序。
    zrem(key, member) :删除名称为key的zset中的元素member
    zincrby(key, increment, member) :如果在名称为key的zset中已经存在元素member,则该元素的score增加increment;否则向集合中添加该元素,其score的值为increment
    zrank(key, member) :返回名称为key的zset(元素已按score从小到大排序)中member元素的rank(即index,从0开始),若没有member元素,返回“nil”
    zrevrank(key, member) :返回名称为key的zset(元素已按score从大到小排序)中member元素的rank(即index,从0开始),若没有member元素,返回“nil”
    zrange(key, start, end):返回名称为key的zset(元素已按score从小到大排序)中的index从start到end的所有元素
    zrevrange(key, start, end):返回名称为key的zset(元素已按score从大到小排序)中的index从start到end的所有元素
    zrangebyscore(key, min, max):返回名称为key的zset中score >= min且score <= max的所有元素
    zcard(key):返回名称为key的zset的基数
    zscore(key, element):返回名称为key的zset中元素element的score
    zremrangebyrank(key, min, max):删除名称为key的zset中rank >= min且rank <= max的所有元素
    zremrangebyscore(key, min, max) :删除名称为key的zset中score >= min且score <= max的所有元素

  • 使用场景:
    例如排行榜

  • 跳表(集合对象的一种编码结构,skiplist,还有一种ziplist)
    1、元素数量小于128 、所有member长度都小于64 使用ziplist
    2、数据量大时针对redis的有序集合和zset的底层依赖是跳表实现的
    3、zset支持快速的插入和删除 首选链表
    4、zset支持范围查询:让链表排序,但是查找的时间复杂度O(n) 效率不高,要满足范围查询的话效率也比较低
    5、为了效率为链表增加索引,如果只增加一层索引的话数据量大的时候效率还是很慢,所以要增加多级索引
    6、所以这种链表增加多级索引的结构就是跳表
    7、 结构上来讲:跳表在原有的链表上每两个增加一个一个指针
    LIYmGu
    8、根据多层链表的想法可以在继续增加层数,增加节点和节点指针的链接的跨度,类似二分查找
    vRYN3z
    qtUmEe
    9、为了解决插入会打乱链接结构问题问题,在插入时会随机出来一个要插入的层数,这样新插入的节点不会影响其他节点的层数,只需要修改新节点的前后指针
    ZirHwu

    二、缓存穿透、缓存击穿、缓存雪崩区别

    1、缓存穿透(缓存和数据库中都没有的数据):

  • 描述:
    缓存和数据库中都没有的数据,而用户不断发起请求。常规情况存储层查不到数据则不写入缓存,导致这个不存在的数据每次请求都要到存储层去查询

  • 解决:
    1)增加查询参数校验,避免一些超过常规情况和非法的参数请求进来,例如(id:-1)
    2)针对在数据库中找不到记录的,仍然将该空数据存入缓存中,设置一个较短的过期时间,如30秒(设置太长会导致正常情况也没法使用)
    3)布隆过滤器(Bloom Filter),可以快速确定数据是否存在

    2、缓存击穿(缓存没有数据和数据库中有数据,热门key,一般是缓存时间到期):

  • 描述:
    缓存击穿表示某个key的缓存非常热门,有很高的并发一直在访问,如果该缓存失效,那同时会走数据库,压垮数据库。

  • 解决:
    1、让该热门key的缓存永不过期。
    2、增加根据key增加互斥锁,通过redis的setnx实现互斥锁

    3、缓存雪崩(大面积缓存同时到期)

  • 描述:
    大面积缓存同时到期,导致大量请求来访问数据库

  • 解决:
    1、设置缓存过期时间时加上一个随机值,避免缓存在同一时间过期

    三、HyperLogLog使用与应用场景

    1、HyperLogLog:

  • 用来做基数统计的算法,结果有 0.81%的误差,和bitmap相比更节省内存

  • bitmap用来数组来表示各元素是否出现

  • HyperLogLog基数统计的算法(去重后的次数),非redis独有

  • 占用内存小

  • hyperloglog key占用了12K的内存用于标记基数

    2、基本使用

  • pfadd 添加 :pfadd m1 1 2 3 4 1 2 3 2 2 2 2

  • pfcount 获得基数值: pfcount m1 //4

  • pfmerge 合并多个key:
    pfadd m1 1 2 3 4 1 2 3 2 2 2 2 //1
    pfcount m1 //4
    pfadd m2 3 3 3 4 4 4 5 5 5 6 6 6 1 //1
    pfcount m2 //5
    pfmerge mergeDes m1 m2 //ok
    pfcount mergeDes //6

    2、使用场景

  • 需要统计的数据基数很大

  • 可以和bitmap配合使用,bitmap标示存在的元素,hyperloglog用来计数

  • 统计注册IP数、在线人数、每日访问的uv、ip等

    四、redis的集群高可用方案

    1、主从模式:

    一个master可以拥有多个slave,但是一个slave只能对应一个master
    主可以读写,从只能读

  • 缺点:
    主库挂了以后服务将不能写入

    2、Sentinel模式(哨兵):

    建立在主从模式的基础上,监听redis的mater的状态,如果master挂掉了,会在slave上选出一台机器作为master
    使用时需要连接sentinel的ip和port而不是redis的

3、Cluster模式:

在需要更大规模的存储的时候主从模式或sentinel模式就不能很好的满足需求了
cluster模式的解决单机Redis容量有限的问题,将Redis的数据根据一定的规则分配到多台机器
redis版本低的话需要安装对应版本的ruby
去中心化的,每个节点(master)都是平等的,连接哪个节点都可以获取和设置数据。

四、内存回收机制

1、内存使用达到maxmemory上限时候触发的溢出回收策略

  • noeviction(默认): 不会删除任何数据,拒绝所有写入操作并返 回客户端错误信息,此 时Redis只响应读操作。
  • volatile-lru: 根据LRU算法删除设置了超时属性(expire)的键,直到腾出足够空间为止。如果没有可删除的键对象,回退到noeviction策略。
  • volatile-ttl: 根据键值对象的ttl属性,删除最近将要过期数据。如果没有,回退到noeviction策略。
  • allkeys-lru: 根据LRU算法删除键,不管数据有没有设置超时属性,直到腾出足够空间为止。
  • volatile-random: 随机删除过期键,直到腾出足够空间为止。
  • allkeys-random: 随机删除所有键,直到腾出足够空间为止。

*** volatile-xxx 策略只会针对带过期时间的 key 进行淘汰,allkeys-xxx 策略会对所有的 key 进行淘汰

2、删除过期时间的键对象

  • 惰性删除 : 当用户访问已经过期的对象的时候才删除
  • 定时任务删除 : 内部维护了一个定时任务,默认每秒运行10次
    1)定时任务在每个数据库空间采用慢模式随机检查20个键,当发现过期时,删除对应的键。
    2)如果超过检查数25%的键过期,循环执行回收逻辑直到不足25%或 运行超时为止,慢模式下超时时间为25毫秒。
    3)如果之前回收键逻辑超时,则在Redis触发内部事件之前再次以快模式运行回收过期键任务,快模式下超时时间为1毫秒且2秒内只能运行1次。
    4)快慢两种模式内部删除逻辑相同,只是执行的超时时间不同

五、其他知识点汇总

1、redis实现延时队列
使用有序合集,使用时间戳做score, 消息内容作为 key
消费者使用 zrangbyscore 获取当前时间之前的数据做轮询处理。