概述

Redis优缺点

长处
  • 读写性能优异。
  • 反对数据长久化,反对AOF和RDB两种长久化形式。
  • 反对事务,Redis的所有操作都是原子性的,同时Redis还反对对几个操作合并后的原子性执行。
  • 反对的数据结构丰盛。
  • 反对主从复制,主机会主动将数据同步到从机,能够进行读写拆散。
毛病
  • 数据库容量受到物理内存的限度。
  • Redis 不具备主动容错和复原性能,主机从机的宕机都会导致前端局部读写申请失败,须要期待机器重启或者手动切换前端的IP能力复原。
  • Redis 较难反对在线扩容,在集群容量达到下限时在线扩容会变得很简单。

Redis为什么这么快

  1. 齐全基于内存,绝大部分申请是纯正的内存操作,十分疾速。
  2. 数据结构简略,对数据操作也简略,Redis 中的数据结构是专门进行设计的。
  3. 采纳单线程,防止了不必要的上下文切换和竞争条件。
  4. 应用多路 I/O 复用模型,非阻塞 IO。

数据结构

Redis反对的数据类型

数据类型能够存储的值操作利用场景
String字符串、整数、浮点数对整个字符串或者其中一部分进行操作<br/>对整数和浮点数进行自增或者自减操作做简略的键值对缓存
List列表从两端压入或弹出元素<br/>对单个或多个元素进行修剪只保留一个范畴内的元素存储一些列表型的数据结构,相似粉丝列表、文章的评论列表之类的数据
Hash蕴含键值对的无序散列表增加、获取、移除键值对<br/>获取所有键值对<br/>查看某个键是否存在存储结构化的数据,比方一个对象
Set无序汇合查看一个元素是否存在于汇合中<br/>计算交加、并集、差集<br/>从汇合外面随机获取元素能够利用交加把两个人的粉丝列表整一个交加
Zset有序汇合依据分值范畴或者成员来获取元素<br/>计算一个键的排名去重但能够排序,如获取排名前几名的用户

三种非凡的数据类型:

  • Geospatial(天文空间)。该性能能够推算出地理位置信息,两地之间的间隔。
  • HyperLogLog。是统计基数的利器,用于统计网站的 UV。
  • bitmap(位图)。通过最小的单位 bit 来进行 0 或者 1 的设置。罕用于统计用户信息,比方沉闷粉丝和不沉闷粉丝、登录和未登录、是否打卡等。

zset跳表的数据结构

利用场景

String的利用场景

  • 商品编号、订单号采纳INCR(递增)命令生成
  • 用INCR记录点赞数
  • 文章的阅读数,只有点击了地址,阅读数就加一。

hash的利用场景

相当于:Map<string, map>

  • 购物车晚期

List的利用场景

  • 微信文章订阅公众号

    1. 公众号公布了文章别离是11和22。
    2. 我关注了他们,只有他们公布了新文章,就会装置进我的List:lpush likeauthor:uid9543 11 22
    3. 查看本人订阅的全副文章,相似分页,上面0~10就是一次性显示10条:lrange likeauthor:uid9543 0 10

Set的利用场景

  • 微信抽奖小程序

    • 一个用户点击参加按钮:SADD key 用户ID
    • 显示曾经有多少人参加:SCARD key
    • 抽奖(从set中任意选取N个中奖人)

      • SPOP key 3,随机抽奖3人,元素会删除
      • SRANDMEMBER key 3,随机抽奖3人,元素不删除
  • 微信敌人圈点赞,并且显示所有点赞的用户
  • 好友的独特关注(交加)
  • 可能意识的人(差集)

Zset的利用场景

  • 依据商品销售对商品进行排序显示(分数是销量)
  • 抖音热搜

长久化

长久化就是把内存的数据写到磁盘中去,避免服务器因为宕机,导致内存数据失落。Redis 反对 RDB(默认) 和 AOF 两种长久化机制,当下次重启时利用之前长久化的文件即可实现数据恢复。

RDB (Redis DataBase) 和 AOF (Append-Only File)

RDB:依照肯定的工夫将内存的数据以快照的形式保留到硬盘中,对应产生的数据文件为 dump.rdb,通过配置文件中的save参数来定义快照的周期。

AOF:只追加文件。将Redis执行的每次写命令记录到独自的日志文件中。

优缺点是什么?

  • AOF 每条数据都写入文件中,比 RDB 更平安。
  • 然而 AOF 文件比 RDB 文件大,且复原速度慢。
  • RDB 性能比 AOF 好。RDB 应用 fork 子过程来实现写操作,让主过程持续解决命令,使 IO 最大化。

如果想数据的安全性更高,应该同时应用两种长久化性能。如果能够接受数分钟以内的数据失落,能够只应用 RDB 长久化。

也不肯定都只应用 AOP,应用 RDB 定时生成 RDB 快照(snapshot)十分便于进行数据库备份。

数据过期

Redis数据过期的删除策略

过期策略通常有以下三种:

定时删除
  • 含意:在设置 key 的过期工夫的同时,为该 key 创立一个定时器,到了过期工夫就会立刻革除该 key。
  • 长处:保障内存尽快开释,对内存敌对。
  • 毛病:会占用大量的 CPU 资源去解决过期的数据,性能影响重大。
惰性删除
  • 含意:key 过期的时候不删除,每次从数据库获取 key 的时候去查看是否过期,若过期,则删除,并返回 null。
  • 长处:能够最大化的节俭 CPU 资源
  • 毛病:若大量的key在超出超时工夫后,很久一段时间内,都没有被获取过,那么可能产生内存泄露(无用的垃圾占用了大量的内存)
定期删除
  • 含意:每隔一段时间执行一次删除过期 key 的操作。
  • 长处和毛病都是介于下面两者之间。
  • 能够设置删除的执行频率,值越大频率越快,对Redis性能损耗也更大。

    能够设置 maxmemory 最大值,当以用内存超过这个值时,就被动触发删除策略。

tips:Redis同时应用了惰性删除与定期删除。

集群计划

随着 Redis 应用场景越来越多,技术倒退越来越欠缺,在 Redis 整体服务上的容错、扩容、稳
定各个方面都须要一直优化。

分布式:一个业务分拆多个子业务,部署在不同的服务器上集群:同一个业务,部署在多个服务器上集群是解决高可用的,而分布式是解决高性能、高并发的

主从模式

为了 Redis 服务防止单点故障,通常的做法是将 Redis 数据复制多个正本以部署在不同的服务器上。这样即便有一台服务器呈现故障,其余服务器仍然能够持续提供服务。

Redis 服务器分为两类:一类是主数据库(Master),另一类是从数据库(Slave)。

主数据库能够进行读写操作,当写操作导致数据变动时会主动将数据同步给从数据库。而从数据库个别是只读的并承受主数据库同步过去的数据。一个主数据库能够领有多个从数据库,而一个从数据库只能领有一个主数据库。

长处:① 一个主,能够有多个从,并以非阻塞的形式实现数据同步;② 扩散主服务的压力,实现读写拆散

毛病:① 不具备容错和复原性能;② Redis 的主从复制采纳全量复制,须要服务器有足够的空余内存

哨兵模式

Redis 提供的哨兵机制,哨兵的作用就是监控 Redis 零碎的运行状况。基本原理是:心跳机制 + 投票裁决。哨兵模式主从能够切换,具备根本的故障转移能力。

它的性能包含以下两个:

  • 监控主数据库和从数据库是否失常运行。
  • 主数据库呈现故障时主动将从数据库转换为主数据库。

心跳机制:在命令流传阶段,从服务器默认以每秒一次的频率,向主服务器发送命令。用于检测主服务器的网络连接状态。

投票裁决:如果主库故障了,依据投票数主动将从库转换为主库。

如何保障缓存与数据库双写时的数据一致性?

  • 读的时候,先读缓存,缓存没有的话,就读数据库,而后取出数据后放入缓存,同时返回响应。
  • 更新的时候,先删除缓存,再更新数据库。如果数据库更新失败了,那么数据库中是旧数据,缓存中是空的,那么数据不会不统一。

内存相干

Redis的内存淘汰策略

Redis的内存淘汰策略是指在Redis的用于缓存的内存不足时,怎么解决须要新写入且须要申请额定空间的数据。

redis为咱们提供了以下 8 种内存淘汰策略:

  1. no-eviction(没有被驱赶):当内存应用超过配置的时候会返回谬误,不会驱赶任何键。
  2. allkeys-lru:移除最久没有应用的键。
  3. volatile-lru:在设置了过期工夫的键中,移除最久没有应用的键。
  4. allkeys-lfu:移除应用频率起码的键。
  5. volatile-lfu:在设置了过期工夫的键中,移除应用频率起码的键。
  6. allkeys-random:随机删除。
  7. volatile-random:在设置了过期工夫的键中,随机删除。
  8. volatile-ttl:在设置了过期工夫的键中,优先删除马上过期的键。

Redis 的内存淘汰策略的选取并不会影响过期的 key 的解决。内存淘汰策略用于解决内存不足时的须要申请额定空间的数据,过期策略用于解决过期的缓存数据。

  • MySQL里有2000w数据,Redis中只存20w的数据,如何保障Redis中的数据都是热点数据?
  1. Redis的内存淘汰策略。
  2. Redis的最大内存设置。

首先计算出20w数据所需的内存空间,设置最大内存,而后抉择适合的内存淘汰策略。

Redis内存用完了会产生什么

如果达到设置的下限,Redis的写命令会返回错误信息,读命令能够失常返回。

缓存异样

缓存雪崩

指缓存同一时间大面积生效,导致前面的申请都会落到数据库上,造成数据库短时间内接受大量申请而崩掉。

解决方案
  1. 优化缓存过期工夫。设置缓存数据的过期工夫时,减少一个随机工夫,避免同一时间大量数据过期。
  2. 放弃缓存层的高可用性。应用Redis 哨兵模式或者Redis 集群部署形式,即使个别Redis 节点下线,整个缓存层仍然能够应用。
  3. 应用互斥锁重建缓存。依据 key 去缓存层查问数据,当缓存层为命中时,对 key 加锁,而后从存储层查问数据,将数据写入缓存层,最初开释锁。

缓存穿透

指查问一个基本不存在的数据,缓存层和存储层都不会命中,导致每次申请都要到存储层去查问,造成数据库短时间内接受大量申请而崩掉。

解决方案
  1. 接口层减少校验。例如用户校验,把 id<0 的间接拦挡。
  2. 缓存空对象。设为 key-null ,缓存无效工夫能够设短些。
  3. 布隆过滤器拦挡。在拜访缓存层和存储层之前,将存在的 key 用布隆过滤器提前保存起来,做第一层拦挡。

缓存击穿

指缓存中没有,但数据库中有的数据(个别是缓存工夫到期),这时因为并发用户特地多,他们同时读缓存没有数据,又同时去数据库中取数据,导致数据库压力增大。

和缓存雪崩不同的是,缓存击穿指并发查同一条数据。而缓存雪崩是不同数据都过期了,很多数据查不到从而查数据库。

解决方案
  1. 设置热点数据永远不过期。
  2. 应用互斥锁重建缓存。

缓存预热

就是零碎上线后,将相干的缓存数据间接加载到缓存零碎。

缓存降级

就是缓存生效或者缓存服务挂掉的状况下,咱们也不去拜访数据库。咱们间接拜访内存局部数据缓存或者间接返回默认数据。

缓存降级的最终目标是保障外围服务可用,即便是有损的。

事务

Redis事务相干命令

  • MULTI 命令:用于开启一个事务,它总是返回OK。
  • EXEC 命令:执行所有事务块内的命令。返回事务块内所有命令的返回值,按命令执行的先后顺序排列。
  • DISCARD 命令:清空事务队列,放弃执行事务,并从事务状态中退出。
  • WATCH 命令:是一个乐观锁,能够为 Redis 提供 CAS 行为。能够监控一个或多个键,一旦其中有一个键被批改或删除,之后的事务就不会执行。监控始终继续到 EXEC 命令。
  • UNWATCH 命令:勾销 WATCH命令 对所有 key 的监控。

Redis事务特点

  • redis事务是一个队列中,一次性、程序性、排他性的执行一系列命令

Redis 在事务失败时不进行回滚,而是继续执行余下的命令。(不反对原子性)

如果在一个事务中的命令编译时呈现语法错误,那么所有的命令都不会执行。放入执行队列时就间接抛出异样。

如果在一个事务中呈现运行谬误,那么正确的命令会被执行。

RedLock

Redis 官网站提出了一种权威的基于 Redis 实现分布式锁的形式名叫 Redlock,此种形式比原先的单节点的办法更平安。

分布式问题

Redis实现分布式锁

Redis为单过程单线程模式,采纳队列模式将并发拜访变成串行拜访,且多客户端对 Redis 的连贯并不存在竞争关系,能够应用 SETNX 命令实现分布式锁。

SETNX key value        # key 不存在时,设置 key 的值。
  1. 应用 SETNX 命令获取锁,若返回 0(key已存在,锁已存在)则获取失败,反之获取胜利。
  2. 为了避免获取锁后程序出现异常,导致其余线程/过程调用 SETNX 命令总是返回 0 而进入死锁状态,须要为该key 设置一个 “正当” 的过期工夫
  3. 开释锁,则应用 DEL 命令将锁数据删除。

Redis的分布式锁的缺点

Redis 高可用最常见的计划就是主从复制(master-slave),这种模式也给 redis 分布式锁挖了一坑。

Redis 集群环境下,如果当初 A 客户端想要加锁,他会依据路由规定抉择一台 master 节点写入 key,在加锁胜利后,master 节点会把 key 复制给对应的 slave 节点。

如果这个时候 master 节点宕机了,进行了主备切换。B 客户端在新的 master 节点上加锁胜利,而 A 客户端也认为本人胜利加了锁。

此时就会导致同一时间内,有多个客户端对一个分布式锁实现了加锁,导致各种脏数据的产生。