Redis

一、为什么要用redis而不用map做缓存?

缓存分为本地缓存和分布式缓存。
map 实现的是本地缓存,生命周期随着jvm 的销毁而结束,并且在多实例的情况下,每个实例都需要各自保存一份缓存,缓存不具有一致性
使用redis 或memcached 之类的称为分布式缓存,在多实例的情况下,各实例共用一份缓存数据,缓存具有一致性。

二、为什么要用 redis/为什么要用缓存?

  1. 高性能:假如用户第一次查询数据库中的某些数据,直接从硬盘读取这个过程比较慢,将用户访问的数据直接存缓存中,那么下次直接从缓存中取即可。
  2. 高并发:直接操作缓存能够承受的请求远远大于直接操作访问数据库,所以可以考虑把数据库的部分数据放入到缓存中。

三、Redis 单线程为什么这么快?

  1. 完全基于内存;
  2. 采用单线程,避免了不必要的上下文切换和竞态条件;
  3. 使用IO 多路复用模型;
  4. 数据结构比较简单,对数据的操作也比较简单。

四、为什么不采用多线程或多进程处理、单线程处理的缺点?

  1. 多线程处理可能会涉及到锁;

  2. 多线程处理会涉及到线程切换而消耗CPU。

  3. 耗时长的命名会导致并发下降,不止是读并发,写并发也会下降;

  4. 无法发挥多核CPU 的性能,不过可以通过单机开多个实例来解决。

五、Redis 的IO 多路复用技术

“多路” 指的是多个网络连接,“复用” 指的是复用同一个Redis 处理线程。


六、Redis 和Memcached 的区别?

  1. Redis 支持更丰富的数据类型:不仅支持简单的k-v 类型数据,还提供了list、set、zset、hash。memcache 支持是String。
  2. Redis 支持数据持久化,可以将内存的数据保存到磁盘中,重启的时候再次加载进行使用。memcached 把数据全部加载到内存中。
  3. 集群模式:memcached 没有原生的集群模式,只能依靠客户端来实现往集群中分片写入数据;但Redis 支持原生的cluster 模式。
  4. memcached 是多线程的,非阻塞IO 复用的网络模型;Redis 使用的是单线程的多路IO 复用模型。

七、Redis 设置过期时间与删除

Redis 有四种方式可以设置过期时间:
set message "hello"

  1. expire message 60 60s的过期时间
  2. pexpire message 60 60毫秒过去时间
  3. expiret message 60 秒时间戳
  4. pexpiret message 毫秒数时间戳

PTTL key 返回key剩余的过期时间(毫秒)。
TTL key返回key剩余的过期时间(秒)。

移除过期时间:
persist message

Redis 删除过期值的策略:

  1. 定期删除:Redis 默认每隔100ms 就随机抽取一些社设置了过期时间的key,检查是否过期,如果过期就删除。 存在问题:到过期时间并没有删除掉。
  2. 惰性删除:定期没有删除没有删掉的数据只有当你再次查询这个key时,才会被Redis 给删掉。

这两种方式都没能及时删除掉过期数据导致内存耗尽:Redis 内存淘汰机制
Redis 提供了6种数据淘汰策略,4.0 后又增加了2种。

八、Redis 的持久化机制

  1. 默认情况下Redis 将数据快照保存为dump.rdb 的二进制文件。
    当Redis 要持久化数据时:
    1.1 Redis 调用forks,同时拥有父进程和子进程
    1.2 子进程将数据集写入到一个临时的RDB 文件中
    1.3 当子进程完成对新RDB 文件的写入时,Redis 用新RDB 文件替换原来的RDB 文件。

  2. AOF 只追加操作的文件
    2.1. AOF 持久化方式需要在配置文件中打开(appendonly yes),可以配置Redis 持久化的方式:
    2.11 每次有新命令就追加AOF 文件一次
    2.12 每秒中执行一次
    2.13 将数据交给操作系统处理,最不安全。

AOF 文件会越来越大,为了处理这种情况,Redis 可以在不打断客户端的情况下,对AOF 文件进行重建(rebuild)。如果AOF 文件损坏,Redis 在重启时会拒绝载入这个AOF 文件,从而确保数据的一致性不被破坏。

九、RDB 和AOF 的优缺点

aof 的优点:
备份数据更稳健,丢失数据的概率更低。
可读写的日志文件,可以处理误操作。
aof 的缺点:
比起rdb 文件占用更多的磁盘空间。
恢复备份速度慢
aof 存储的写指令,rdb 存储的数据。

十、Redis 的集群

1. 一主二仆模式

主机可读可写,从机只能读
从机是从开始复制而非从切入点开始复制(无论何时宕机)。
主机shutdow 后,从机仍然是从机,不会变成主机(没有哨兵模式)。

2.薪火相传模式(主—> 从 —> 从)

一旦某台服务器宕机,后面的从机都无法备份。
从服务器仍然不能变成主服务器。

3.哨兵模式

反客为主的自动版

十一、缓存穿透、缓存击穿、缓存雪崩

  1. 缓存雪崩:缓存同一时间大面积失效,所有的请求都落在数据库上,造成数据库在短时间内承受大量的请求而崩掉。
    解决办法:
    事前:保证Redis 集群的高可用性,选择合适的内存淘汰策略;
    事中:本地ehcache 缓存 + hystrix 限流&降级,避免MySQL崩掉;
    事后:利用Redis 持久化机制将保持的数据尽快恢复

  2. 缓存穿透:大量请求的key 在缓存中根本不存在,导致请求直接打在数据库上,根本没有经过缓存一层。


    一般MySQL 默认的最大连接数在 150 左右,这个可以通过 show variables like '%max_connections%'; 命令来查看。cpu,内存,磁盘,网络等无力条件都是其运行指标,这些指标都会限制其并发能力!所以,一般 3000 个并发请求就能打死大部分数据库了。
    解决办法:
    2.1 做好参数校验,比如id不能小于0 等;
    2.2 缓存无效key,这种方式可以解决key 变化不频繁的情况,如果key 变化频繁则建议key 的过期时间设置短一点。
    2.3 布隆过滤器:我们需要的就是判断 key 是否合法,把所有可能存在的请求的值都存放在布隆过滤器中,当用户请求过来,我会先判断用户发来的请求的值是否存在于布隆过滤器中。不存在的话,直接返回请求参数错误信息给客户端,存在的话才会走下面的流程。

    关于布隆过滤器的介绍

  3. 缓存击穿

一般情况下我们是这样设计 key 的: 表名:列名:主键名:主键值。

十二、Redis 的事务以及相关的命令

multi......命令......exec
discard 取消事务
redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚。
组队中某个命令出现了报告错误,执行时整个的队列都会被取消。
watch key
在执行multi 之前,可以先执行watch 命令,监视一个或多个key,如果在执行事务之前这些key 被其它命令所改动,则事务将被打断。watch 与 multi 之间不允许有任何的 set key1 value操作。

十三、如何解决 Redis 的并发竞争 Key 问题

并发竞争 Key 的问题也就是多个系统同时对一个 key 进行操作。
推荐一种方案:分布式锁(zookeeper 和 redis 都可以实现分布式锁)。如果不存在 Redis 的并发竞争 Key 问题,不要使用分布式锁,这样会影响性能。

十四、如何保证缓存与数据库双写时的数据一致性?

https://github.com/doocs/advanced-java/blob/master/docs/high-concurrency/redis-consistence.md

你可能感兴趣的:(Redis)