Redis的一些简单总结

Redis的一些简单总结

1.什么是Redis?为什么要用Redis?

主要从“高性能”和“高并发”这两点来看待这个问题。
高性能
假如用户第一次访问数据库中的某些数据。这个过程会比较慢,因为是从硬盘上读取的。将该用户访问的数据存在数 缓存中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了。操作缓存就是直接操作内存,所以速度相当快。如果数据库中的对应数据改变的之后,同步改变缓存中相应的数据即可!
高并发
直接操作缓存能够承受的请求是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。

2.redis的过期策略都有哪些?内存淘汰机制都有哪些?

1)案例:咦!我往redis里写的数据怎么没了?
我们生产环境的redis怎么经常会丢掉一些数据?写进去了,过一会儿可能就没了。我的天,这个问题就说明redis你就没用对啊。redis是缓存,你给当存储了是吧?
啥叫缓存?用内存当缓存。内存是无限的吗,内存是很宝贵而且是有限的,磁盘是廉价而且是大量的。可能一台机器就几十个G的内存,但是可以有几个T的硬盘空间。redis主要是基于内存来进行高性能、高并发的读写操作的。
那既然内存是有限的,比如redis就只能用10个G,你要是往里面写了20个G的数据,会咋办?当然会干掉10个G的数据,然后就保留10个G的数据了。那干掉哪些数据?保留哪些数据?当然是干掉不常用的数据,保留常用的数据了。

所以说,这是缓存的一个最基本的概念,数据是会过期的,要么是你自己设置个过期时间,要么是redis自己给干掉。

set key value 过期时间(1小时)
set进去的key,1小时之后就没了,就失效了。
2)案例:我的数据明明都过期了,怎么还占用着内存啊?
还有一种就是如果你设置好了一个过期时间,你知道redis是怎么给你弄成过期的吗?什么时候删除掉?如果你不知道,之前有个学员就问了,为啥好多数据明明应该过期了,结果发现redis内存占用还是很高?那是因为你不知道redis是怎么删除那些过期key的。

redis 内存一共是10g,你现在往里面写了5g的数据,结果这些数据明明你都设置了过期时间,要求这些数据1小时之后都会过期,结果1小时之后,你回来一看,redis机器,怎么内存占用还是50%呢?5g数据过期了,我从redis里查,是查不到了,结果过期的数据还占用着redis的内存。
如果你连这个问题都不知道,上来就懵了,回答不出来,那线上你写代码的时候,想当然的认为写进redis的数据就一定会存在,后面导致系统各种漏洞和bug,谁来负责?
1)设置过期时间

我们set key的时候,都可以给一个expire time,就是过期时间,指定这个key比如说只能存活1个小时?10分钟?这个很有用,我们自己可以指定缓存到期就失效。
如果假设你设置一个一批key只能存活1个小时,那么接下来1小时后,redis是怎么对这批key进行删除的?

答案是:定期删除+惰性删除
所谓定期删除,指的是redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。假设redis里放了10万个key,都设置了过期时间,你每隔几百毫秒,就检查10万个key,那redis基本上就死了,cpu负载会很高的,消耗在你的检查过期key上了。注意,这里可不是每隔100ms就遍历所有的设置过期时间的key,那样就是一场性能上的灾难。实际上redis是每隔100ms随机抽取一些key来检查和删除的。

但是问题是,定期删除可能会导致很多过期key到了时间并没有被删除掉,那咋整呢?所以就是惰性删除了。这就是说,在你获取某个key的时候,redis会检查一下 ,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。
并不是key到时间就被删除掉,而是你查询这个key的时候,redis再懒惰的检查一下。
通过上述两种手段结合起来,保证过期的key一定会被干掉。
很简单,就是说,你的过期key,靠定期删除没有被删除掉,还停留在内存里,占用着你的内存呢,除非你的系统去查一下那个key,才会被redis给删除掉。

但是实际上这还是有问题的,如果定期删除漏掉了很多过期key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期key堆积在内存里,导致redis内存块耗尽了,咋整?

答案是:走内存淘汰机制。

2)内存淘汰

如果redis的内存占用过多的时候,此时会进行内存淘汰,有如下一些策略:

redis 10个key,现在已经满了,redis需要删除掉5个key

1个key,最近1分钟被查询了100次
1个key,最近10分钟被查询了50次
1个key,最近1个小时倍查询了1次

1)noeviction:当内存不足以容纳新写入数据时,新写入操作会报错,这个一般没人用吧,实在是太恶心了
2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的)
3)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key,这个一般没人用吧,为啥要随机,肯定是把最近最少使用的key给干掉啊
4)volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key(这个一般不太合适)
5)volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key
6)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。

3. Redis 常见异常及解决方案

了解什么是redis的雪崩和穿透?redis崩溃之后会怎么样?系统该如何应对这种情况?如何处理redis的穿透?
缓存雪崩发生的现象

Redis的一些简单总结
缓存雪崩的事前事中事后的解决方案
Redis的一些简单总结

事前:redis高可用,主从+哨兵,redis cluster,避免全盘崩溃
事中:本地ehcache缓存 + hystrix限流&降级,避免MySQL被打死
事后:redis持久化,快速恢复缓存数据
缓存穿透的现象
缓存穿透的解决方法Redis的一些简单总结

4.redis 持久化机制(怎么保证 redis 挂掉之后再重启数据可以进行恢复)

Redis的一些简单总结
多时候我们需要持久化数据也就是将内存中的数据写入到硬盘里面,大部分原因是为了之后重用数据(比如重启机 器、机器故障之后回复数据),或者是为了防止系统故障而将数据备份到一个远程位置。
Redis支持两种不同的持久化操作:
Redis的一种持久化方式叫快照(snapshotting,RDB),另一种方式是只追加文件(append-only fifile,AOF).这两种方法各有千秋,下面我会详细这两种持久化方法是什么,怎么用,如何选择适合自己的持久化方法。
1.快照(snapshotting)持久化(RDB)
Redis可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。Redis创建快照之后,可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis主从结构,主要用来提高Redis性能),还可以将快照留在原地以便重启服务器的时候使用。快照持久化是Redis默认采用的持久化方式,在redis.conf配置文件中默认有此下配置:
save 900
1
令创建快照。
#在900秒(15分钟)之后,如果至少有1个key发生变化,Redis就会自动触发BGSAVE命
save 300 10
令创建快照。
#在300秒(5分钟)之后,如果至少有10个key发生变化,Redis就会自动触发BGSAVE命
save 60 10000
令创建快照。
#在60秒(1分钟)之后,如果至少有10000个key发生变化,Redis就会自动触发BGSAVE命aof-use-rdb-preambl
AOF(append-only fifile)持久化
与快照持久化相比,AOF持久化 的实时性更好,因此已成为主流的持久化方案。默认情况下Redis没有开启AOF(append only fifile)方式的持久化,可以通过appendonly参数开启:
开启AOF持久化后每执行一条会更改Redis中的数据的命令,Redis就会将该命令写入硬盘中的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的,默认的文件名是appendonly.aof。
在Redis的配置文件中存在三种不同的 AOF 持久化方式,它们分别是:
为了兼顾数据和写入性能,用户可以考虑 appendfsync everysec选项 ,让Redis每秒同步一次AOF文件,Redis性能几乎没受到任何影响。而且这样即使出现系统崩溃,用户最多只会丢失一秒之内产生的数据。当硬盘忙于执行写入操 作的时候,Redis还会优雅的放慢自己的速度以便适应硬盘的最大写入速度。
Redis 4.0 对于持久化机制的优化
Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,可以通过配置项 开启)。
如果把混合持久化打开,AOF 重写的时候就直接把 RDB 的内容写到 AOF 文件开头。这样做的好处是可以结合 RDB和 AOF 的优点, 快速加载同时避免丢失过多的数据。当然缺点也是有的, AOF 里面的 RDB 部分是压缩格式不再是
AOF 格式,可读性较差。
补充内容:AOF 重写
AOF重写可以产生一个新的AOF文件,这个新的AOF文件和原有的AOF文件所保存的数据库状态一样,但体积更小。
AOF重写是一个有歧义的名字,该功能是通过读取数据库中的键值对来实现的,程序无须对现有AOF文件进行任伺读 入分析或者写入操作。
在执行 BGREWRITEAOF 命令时,Redis 服务器会维护一个 AOF 重写缓冲区,该缓冲区会在子进程创建新AOF文件期间,记录服务器执行的所有写命令。当子进程完成创建新AOF文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新AOF文件的末尾,使得新旧两个AOF文件所保存的数据库状态一致。最后,服务器用新的AOF文件替换旧的AOF文件,以此来完成AOF文件重写操作。

5.Redis 集群模式

作为缓存数据库,肯定要考虑缓存服务稳定性相关的保障机制。
持久化机制就是一种保障方式。持久化机制保证了 Redis 服务器重启的情况下也不会损失(或少量损失)数据,因为持久化会把内存中数据保存到硬盘上,重启会从硬盘上加载数据。随着Redis使用场景越来越多,技术发展越来越完善,在 Redis 整体服务上的容错、扩容、稳定各个方面都需要不断优化。 因此在 Redis 的集群模式上也有不同的搭建方式来应对各种需求。
总结来说,Redis 集群模式有三种:
 主从模式
 哨兵模式
 Cluster 集群模式
01 主从模式
Redis的一些简单总结
为了 Redis 服务避免单点故障,通常的做法是将 Redis 数据复制多个副本以部署在不同的服务器上。这样即使有一台服务器出现故障,其他服务器依然可以继续提供服务。为此,Redis 提供了复制( replication )功能,可以实现当一台数据库中的数据更新后,自动将更新的数据同步到其他数据库上。
Redis 服务器分为两类:一类是主数据库(Master),另一类是从数据库(Slave)。
主数据库可以进行读写操作,当写操作导致数据变化时会自动将数据同步给从数据库。 从数据库一般是只读的,并接受主数据库同步过来的数据。一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库。
优点

  1. 一个主,可以有多个从,并以非阻塞的方式完成数据同步;
  2. 从服务器提供读服务,分散主服务的压力,实现读写分离;
  3. 从服务器之前可以彼此连接和同步请求,减少主服务同步压力。
    缺点
  4. 不具备容错和恢复功能,主服务存在单点风险;
  5. Redis 的主从复制采用全量复制,需要服务器有足够的空余内存;
  6. 主从模式较难支持在线扩容。
    02 哨兵模式
    Redis的一些简单总结
    Redis 提供的 sentinel(哨兵)机制,通过 sentinel 模式启动redis后,自动监控 Master/Slave的运行状态,基本原理是:心跳机制 + 投票裁决。
    简单来说,哨兵的作用就是监控 Redis 系统的运行状况。它的功能包括以下两个:
  7. 监控主数据库和从数据库是否正常运行;
  8. 主数据库出现故障时自动将从数据库转换为主数据库。
    哨兵模式主要有下面几个内容:
     监控( Monitoring ):Sentinel 会定期检查主从服务器是否处于正常工作状态。
     提醒( Notification ):当被监控的某个 Redis 服务器出现异常时,Sentinel 可以通过 API 向管理员或者其他应用程序发送通知
    自动故障迁移(Automatic failover):当一个主服务器不能正常工作时,Sentinel 会开始一次自动故障迁移操作,它会将失效主服务器的其中一个从服务器升级为新的主服务器,并让失效主服务器的其他从服务器改为复制新的主服务器;当客户端试图连接失效的主服务器时,集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。Redis Sentinel 是一个分布式系统,你可以在一个架构中运行多个 Sentinel 进程( progress )。
    优点
  9. 哨兵模式主从可以切换,具备基本的故障转移能力;
  10. 哨兵模式具备主从模式的所有优点。
    缺点
  11. 哨兵模式也很难支持在线扩容操作;
  12. 集群的配置信息管理比较复杂。
    03 Cluster 集群模式

Redis的一些简单总结
Redis Cluster 是一种服务器 Sharding 技术,3.0 版本开始正式提供。采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。如图所示:Cluster 集群结构特点:

  1. Redis Cluster 所有的物理节点都映射到 [ 0-16383 ] slot 上(不一定均匀分布),Cluster负责维护节点、桶、值之间的关系;
  2. 在 Redis 集群中放置一个 key-value 时,根据 CRC16(key) mod 16384 的值,从之前划分的 16384 个桶中选择一个;
  3. 所有的 Redis 节点彼此互联(PING-PONG 机制),内部使用二进制协议优化传输效率;
  4. 超过半数的节点检测到某个节点失效时则判定该节点失效;
  5. 使用端与 Redis 节点链接,不需要中间 proxy 层,直接可以操作,使用端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
    优点
  6. 无中心架构,节点间数据共享,可动态调整数据分布;
  7. 节点可动态添加删除,扩展性比较灵活;
  8. 部分节点异常,不影响整体集群的可用性。
    缺点
  9. 集群实现比较复杂;
  10. 批量操作指令( mget、mset 等)支持有限;
  11. 事务操作支持有限。