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、 结构上来讲:跳表在原有的链表上每两个增加一个一个指针
8、根据多层链表的想法可以在继续增加层数,增加节点和节点指针的链接的跨度,类似二分查找
9、为了解决插入会打乱链接结构问题问题,在插入时会随机出来一个要插入的层数,这样新插入的节点不会影响其他节点的层数,只需要修改新节点的前后指针二、缓存穿透、缓存击穿、缓存雪崩区别
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 //62、使用场景
需要统计的数据基数很大
可以和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 获取当前时间之前的数据做轮询处理。