1.Redis为什么快?

Redis完全基于内存,大部分都是简单的存取操作,大量的时间花费在IO上。Redis绝大部分操作时间复杂度为O(1),所以速度十分快。


2.Redis的数据类型?

● key-string:一个key对应一个值。
● key-hash:一个key对应一个Map。集合,多个元素
● key-list:一个key对应一个List列表。集合,多个元素
● key-set:一个key对应一个Set集合。集合,多个元素
● key-zset:一个key对应一个有序的Set集合。等价于:Map
另外3种数据结构:
● geospatial:地理位置。
● bitmaps:一般存储的也是一个字符串,存储的是一个byte[]。
● hyperloglogs:计算近似值的。


3.Redis的过期策略?

key的生存时间到了,Redis会立即删除吗?不会立即删除。
有以下几种策略:
- 定期删除:Redis每隔一段时间就去会去查看Redis设置了过期时间的key,会再100ms的间隔中默认查看3个key。
- 惰性删除:如果当你去查询一个已经过了生存时间的key时,Redis会先查看当前key的生存时间,是否已经到了,直接删除当前key,并且给用户返回一个空值。


4.Redis的淘汰机制?


当redis内存快耗尽时,redis会启动内存淘汰机制,将部分key清掉以腾出内存。
redis提供6中数据淘汰策略,可在redis.conf中配置:maxmemory-policy noeviction
noeviction:禁止驱逐数据。默认配置都是这个。当内存使用达到阀值的时候,所有引起申请内存的命令都会报错。
volatile-lru:从设置了过期时间的数据集中挑选最近最少使用的数据淘汰。
volatile-ttl:从已设置了过期时间的数据集中挑选即将要过期的数据淘汰。
volatile-random:从已设置了过期时间的数据集中任意选择数据淘汰。
allkeys-lru:从数据集中挑选最近最少使用的数据淘汰。
allkeys-random:从数据集中任意选择数据淘汰。

5. Redis操作分布式锁

分布式锁就是在多个节点都可以访问得位置设置一个标志
任何节点想访问被锁得资源时,首先尝试获取这个标志
如果获取成功表示获取锁成功 失败表示获取锁失败
使用redis实现分布式锁就是
准备一个redis节点在redis设置一个key作为锁标志
当key存在时,就表示资源被锁
当key不存在,就表示资源处于空闲状态
加锁得过程就是 判断key是都存在
如果key不存在就添加一个
这里要注意的是判断key是否存在和添加key的过程必须是原子操作
使用的是redis的setnx方法,
资源使用完成,再将key删除,也就是释放锁,
这里同样是原子性操作
可是持有锁的节点在释放锁之前宕机了会导致锁永远无法被释放
解决方案是添加key的时候,给key设置一个过期时间
即使持有锁的节点宕机了,redis也会自动释放锁
但还是有问题 比如一个线程使用锁的时间超过key设置的时间
会导致持有锁的节点还没结束,锁就被redis释放了
解决方案是 当某个结点获取到锁之后
立刻获取到一个子线程给自己续命 子线程的主要任务就是等key的过期时间快到的时候
一般还剩1/3的时间的时候,重新给key设置一下过期时间 和 之前的过期时间一样
当持有锁的节点完成操作之后,显示主动关闭子线程,后释放锁
当持有锁的节点宕机之后,续命子线程也不会执行,redis就会自动释放锁

6. Redis持久化

Redis提供2种方式实现持久化:1.RDB 2.AOF
同时开启RDB和AOF的注意事项:
如果同时开启了AOF和RDB持久化,那么在Redis宕机重启之后,需要加载一个持久化文件,优先选择AOF文件。
如果先开启了RDB,再次开启AOF,如果RDB执行了持久化,那么RDB文件中的内容会被AOF覆盖掉。

6.1 RDB

RDB是Redis默认的持久化机制
RDB持久化文件,速度比较快,而且存储的是一个二进制的文件,传输起来很方便。
RDB持久化的时机:
save 900 1:在900秒内,有1个key改变了,就执行RDB持久化。
save 300 10:在300秒内,有10个key改变了,就执行RDB持久化。
save 60 10000:在60秒内,有10000个key改变了,就执行RDB持久化。
RDB无法保证数据的绝对安全。

6.2 AOF

AOF持久化机制默认是关闭的,Redis官方推荐同时开启RDB和AOF持久化,更安全,避免数据丢失。
AOF持久化的速度,相对RDB较慢的,存储的是一个文本文件,到了后期文件会比较大,传输困难。
AOF持久化时机。
appendfsync always:每执行一个写操作,立即持久化到AOF文件中,性能比较低。
appendfsync everysec:每秒执行一次持久化。
appendfsync no:会根据你的操作系统不同,环境的不同,在一定时间内执行一次持久化。
AOF相对RDB更安全,推荐同时开启AOF和RDB。

7. Redis的集群策略

1.主从复制
单机版 Redis存在读写瓶颈的问题
image.png
2.哨兵机制
哨兵可以帮助我们解决主从架构中的单点故障问题
3.集群多主多从
Redis-Cluster
Redis集群在保证主从加哨兵的基本功能之外,还能够提升Redis存储数据的能力
image.png

8. Redis 事务

Redis 事务可以一次执行多个命令, 并且带有以下三个重要的保证:

  • 批量操作在发送 EXEC 命令前被放入队列缓存。
  • 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。
  • 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。

一个事务从开始到执行会经历以下三个阶段:

  • 开始事务。
  • 命令入队。
  • 执行事务。

以下是一个事务的例子, 它先以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事务, 一并执行事务中的所有命令:

  1. redis 127.0.0.1:6379> MULTI
  2. OK
  3. redis 127.0.0.1:6379> SET book-name "Mastering C++ in 21 days"
  4. QUEUED
  5. redis 127.0.0.1:6379> GET book-name
  6. QUEUED
  7. redis 127.0.0.1:6379> SADD tag "C++" "Programming" "Mastering Series"
  8. QUEUED
  9. redis 127.0.0.1:6379> SMEMBERS tag
  10. QUEUED
  11. redis 127.0.0.1:6379> EXEC
  12. 1) OK
  13. 2) "Mastering C++ in 21 days"
  14. 3) (integer) 3
  15. 4) 1) "Mastering Series"
  16. 2) "C++"
  17. 3) "Programming"

单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。
事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,也不会造成后续的指令不做。

这是官网上的说明 From redis docs on** **transactions:
即使一个命令失败了,队列中的所有其他命令都被处理了——Redis不会停止对命令的处理。

比如:

  1. redis 127.0.0.1:7000> multi
  2. OK
  3. redis 127.0.0.1:7000> set a aaa
  4. QUEUED
  5. redis 127.0.0.1:7000> set b bbb
  6. QUEUED
  7. redis 127.0.0.1:7000> set c ccc
  8. QUEUED
  9. redis 127.0.0.1:7000> exec
  10. 1) OK
  11. 2) OK
  12. 3) OK

如果在 set b bbb 处失败,set a 已成功不会回滚,set c 还会继续执行。

Redis 事务命令

下表列出了 redis 事务的相关命令

  1. Discard - 取消事务,放弃执行事务块内的所有命令
  2. Exec - 执行所有事务块的命令
  3. Multl - 标记一个事务块的开始
  4. Unwatch - 取消Watch命令 对所有Key的监视。
  5. Watch key [key…] - 监视一个key或者多个key(key…),如果在事务执行之前这些key被其他命令所改动,事务将会被打断

9. Redis的击穿雪崩穿透倾斜

9.1击穿

Redis - 图3

9.2雪崩

Redis - 图4

9.3穿透

Redis - 图5

9.4倾斜

Redis - 图6