Redis 相关知识点汇总

一、关于 Redis

1.Redis 是什么

  Redis 是一个开放源代码(BSD 许可)的内存中数据结构存储,可用作数据库,缓存和消息代理,是一个基于键值对的 NoSQL 数据库。

2.Redis 特性有哪些

  • 速度快
  • 基于键值对的数据结构服务器
  • 丰富的功能、丰富的数据结构
  • 简单稳定
  • 客户端语言多
  • 持久化
  • 主从复制
  • 高可以 & 分布式

3.Redis 合适的应用场景

  • 缓存
  • 排行榜
  • 计数器
  • 分布式会话
  • 分布式锁
  • 社交网络
  • 最新列表
  • 消息系统

4.除了 Redis 以外的 NoSQL 数据库

  MongoDB、MemcacheDB、Cassandra、CouchDB、Hypertable、Leveldb。

5.Redis 和 Memcache 区别

  • 支持的存储类型不同,memcached 只支持简单的 k/v 结构。redis 支持更多类型的存储结构类型(详见问题6)。
  • memcached 数据不可恢复,redis 则可以把数据持久化到磁盘上。
  • 新版本的 redis 直接自己构建了 VM 机制 ,一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
  • redis 当物理内存用完时,可以将很久没用到的 value 交换到磁盘。

6.Redis 的几种数据类型

   基础:字符串(String)、哈希(hash)、列表(list)、集合(set)、有序集合(zset)。

   还有HyperLogLog、流、地理坐标等。

7.Redis 的高级功能

  消息队列、自动过期删除、事务、数据持久化、分布式锁、附近的人、慢查询分析、Sentinel 和集群等多项功能。

 

二、Redis 启动和执行

1.Redis 几个比较主要的可执行文件

 

 

 

2.启动 Redis 的几种方式

  1. 默认配置 : ./redis-server
  2. 运行启动: redis-server 加上要修改配置名和值(可以是多对),没有配置的将使用默认配置。例如: redis-server ———port 7359
  3. 指定配置文件启动: ./redis-server/opt/redis/redis.conf

3.Redis 配置自定义配置

  redis 目录下有一个 redis.conf 的模板配置。只需要复制模板配置然后修改即可。

  一般来说大部分生产环境都会用指定配置文件的方式启动redis。

4.Redis 客户端命令执行的方式

  • (1)交互方式:
    redis-cli -h 127.0.0.1 -p 6379
    # 连接到redis后,后面执行的命令就可以通过交互方式实现了。
  • (2)命令行方式:
    redis-cli -h 127.0.0.1 -p 6379 get value

5.停止 Redis 服务

  1. Kill-9 pid (粗暴,请不要使用,数据不仅不会持久化,还会造成缓存区等资源不能被优雅关闭)。
  2. 可以用 redis 的 shutdown 命令,可以选择是否在关闭前持久化数据。
    redis-cli shutdown nosave|save

6.如何查看当前键是否存在?

  exists key

7.如何删除数据?

  del key

 

三、Redis 注意事项

1.Redis 为什么快

  • redis 使用了单线程架构和 I/O 多路复用模型模型。
  • 纯内存访问。
  • 由于是单线程避免了线程上下文切换带来的资源消耗。
  •  C语言实现,优化过的数据结构,基于几种基础的数据结构,redis做了大量的优化,性能极高

C语言实现,优化过的数据结构,基于几种基础的数据结构,redis做了大量的优化,性能极高

2.为什么 Redis6.0 是想用多线程

  redis 使用多线程并非是完全摒弃单线程,redis 还是使用单线程模型来处理客户端的请求,只是使用多线程来处理数据的读写和协议解析,执行命令还是使用单线程。

  这样做的目的是因为 redis 的性能瓶颈在于网络 IO 而非 CPU,使用多线程能提升 IO 读写的效率,从而整体提高 redis 的性能。

3.字符串最大不能超过多少

  512MB。

4.Redis 默认分多少个数据库

  16个。

5.Redis 持久化的几种方式?

  RDB、AOF、混合持久化。

 

四、RDB 持久化

  RDB(Redis DataBase)持久化是把当前进程数据生成快照保存到硬盘的过程。

  Tips:是以二进制的方式写入磁盘。

1.RDB 的持久化是如何触发的?

  1. 手动触发:
    • save :阻塞当前 Redis 服务器,直到 RDB 过程完成为止,如果数据比较大的话,会造成长时间的阻塞,线上不建议。
    • bgsave:redis 进程执行 fork 操作创作子进程,持久化由子进程负责,完成后自动结束,阻塞只发生在fork阶段,一半时间很短。 
  2. 自动触发:
    • savexsecends n: 表示在 x 秒内,至少有 n 个键发生变化,就会触发 RDB 持久化。也就是说满足了条件就会触发持久化。
    • flushall:主从同步触发

2.RDB 的优点

  • rdb 是一个紧凑的二进制文件,代表 Redis 在某个时间点上的数据快照。
  • 适合于备份,全量复制的场景,对于灾难恢复非常有用。
  • Redis 加载 RDB 恢复数据的速度远快于 AOF 方式。

3.RDB的缺点

  • RDB 没法做到实时的持久化。中途意外终止,会丢失一段时间内的数据。
  • RDB 需要 fork() 创建子进程,属于重量级操作,可能导致 Redis卡顿若干秒。

4.如何禁用持久化

  一般来说生成环境不会用到,了解一下也有好处的。

config set save ""

 

五、AOF 持久化

  AOF(appendonly file)为了解决 rdb 不能实时持久化的问题,aof 来搞定。以独立的日志方式记录把每次命令记录到 aof 文件中。

1.如何查询 AOF 是否开启

config get appendonly

2.如何开启 AOF

  • 命令行方式:实时生效,但重启后失效。
    config set appendonly
  • 配置文件:需要重启生效,重启后依然生效。
    appendonly yes

3.AOF 的工作流程

  1. 所有写入命令追加到 aof_buf 缓冲区。
  2. AOF 缓冲区根据对应的策略向硬盘做同步操作。
  3. 随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
  4. 当 redis 服务器重启时,可以加载 AOF 文件进行数据恢复。

4.为什么 AOF 要先把命令追加到缓存区(aof_buf)中

  Redis 使用单线程响应命令,如果每次写入文件命令都直接追加到硬盘,性能就会取决于硬盘的负载。如果使用缓冲区,redis提供多种缓冲区策略,在性能和安全性方面做出平衡。

5.AOF 持久化如何触发的

  • 自动触发:满足设置的策略和满足重写触发。策略:(在配置文件中配置

     

  • 手动触发:(执行命令)
    bgrewriteaof 

6.AOF 优点

  • AOF 提供了 3 种保存策略:每秒保存、跟系统策略、每次操作保存。实时性比较高,一般来说会选择每秒保存,因此意外发生时顶多失去一秒的数据。
  • 文件追加写形式,所以文件很少有损坏问题,如最后意外发生少写数据,可通过 redis-check-aof 工具修复。
  • AOF 由于是文本形式,直接采用协议格式,避免二次处理开销,另外对于修改也比较灵活。

7.AOF 缺点

  • AOF 文件要比 RDB 文件大。
  • AOF 冷备没 RDB 迅速。
  • 由于执行频率比较高,所以负载高时,性能没有 RDB 好。

 

六、混合持久化

  一般来说线上都会采取混合持久化。redis4.0 以后添加了新的混合持久化方式。

1.优点:

  在快速加载的同时,避免了丢失过更多的数据。

2.缺点:

  • 由于混合了两种格式,所以可读性差。
  • 兼容性,需要 4.0 以后才支持。

 

七、缓存

1. 缓存穿透

  正常情况下,我们去查询数据都是存在。那么请求去查询一条数据库中根本就不存在的数据,也就是缓存和数据库都查询不到这条数据,但是请求每次都会打到数据库上面去。这种查询不存在数据的现象称为缓存穿透。

  缓存穿透产生大量的请求到数据库去查询。可能会导致数据库由于压力过大而宕机。

解决方案:在缓存中将该键对应的值为设置为 null,配置过期时间

2.缓存击穿

  在平常高并发的系统中,大量的请求同时查询一个 key 时,此时若这个 key 正好失效了,就会导致大量的请求都打到数据库上面去。这种现象即缓存击穿。

解决方案:缓存击穿的现象是多个线程同时去查询数据库的同一条数据,可以在第一个查询数据的请求上使用一个互斥锁来锁住它。其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存。

3.缓存雪崩

  当某一时刻发生大规模的缓存失效的情况。比如缓存服务宕机或集中过期,会有大量的请求直接打到DB上。结果 DB 称不住,挂掉。

解决方案

  • 事前:使用集群缓存,保证缓存服务的高可用。如果是使用 Redis,可以使用 主从+哨兵 ,Redis Cluster 来避免 Redis 全盘崩溃的情况。

  • 事中:使用 ehcache 本地缓存 + Hystrix 限流&降级 ,避免 MySQL 被打死的情况发生。使用 Hystrix 进行 限流 & 降级 ,比如一秒来了5000个请求,可以设置假设只能有一秒 2000 个请求能通过这个组件,那么其他剩余的 3000 请求就会走限流逻辑,然后去调用降级组件(降级)。比如设置的一些默认值呀之类的。以此来保护最后的 MySQL 不会被大量的请求给打死。

  • 事后:开启 Redis 持久化机制,尽快恢复缓存集群

4.缓存预热

  系统上线后,提前将相关数据加载到缓存系统,避免用户先查库,然后在缓存。

八、其他

1.安装 Redis 步骤

  • 下载 Redis 指定版本源码安装包压缩到当前目录。
  • 解压缩 Redis 源码安装包。
  • 建立一个 redis 目录软链接,指向解压包。
  • 进入 redis 目录
  • 编译
  • 安装

  或者:docker pull redis。

2.Redis 事务

  事务提供了一种将多个命令请求打包,一次性、按顺序的执行多个命令的机制。并且在事务执行期间,服务器不会中断事务而改去执行其他客户端命令请求,它会

3.Redis 事务开始到结束的几个阶段?

  • 开启事务
  • 命令入队
  • 执行事务/放弃事务

4.Redis 中 key 的过期操作?

# 设置key的生存时间为n秒:
expire key nseconds

# 设置key的生存时间为nmilliseconds:
pxpire key milliseconds

# 设置过期时间为timestamp所指定的秒数时间戳:
expireat key timespamp

# 设置过期时间为timestamp毫秒级时间戳:
pexpireat key millisecondsTimestamp

5.Redis 过期键删除策略?

  • 定时删除:在设置的过期时间同时,创建一个定时器在键的过期时间来临时,立即执行队键的操作删除。
  • 惰性删除:放任过期键不管,但每次从键空间中获取键时,都检查取得的键是否过期,如果过期就删除,如果没有就返回该键。
  • 定期删除:每隔一段时间执行一次删除过期键操作,并通过先吃删除操作执行的时长和频率来减少删除操作对 CPU 时间的影响。

定期+惰性都没有删除怎么办

假设 redis 每次定期随机查询 key 的时候没有删掉,这些 key 也没有做查询的话,就会导致这些key一直保存在 redis 里面无法被删除,这时候就会走到 redis 的内存淘汰机制。

  1. volatile-lru:从已设置过期时间的key中,移出最近最少使用的key进行淘汰
  2. volatile-ttl:从已设置过期时间的key中,移出将要过期的key
  3. volatile-random:从已设置过期时间的key中随机选择key淘汰
  4. allkeys-lru:从key中选择最近最少使用的进行淘汰
  5. allkeys-random:从key中随机选择key进行淘汰
  6. noeviction:当内存达到阈值的时候,新写入操作报错

6.Pipeline

  命令批处理技术,对命令进行组装,然后一次性执行多个命令。可以有效的节省 RTT(Round Trip Time 往返时间)。

经过测试验证:

  • pipeline 执行速度一般比逐条执行快。
  • 客户端和服务的网络延越大,pipeline 效果越明显。

7.如何获取当前最大内存?如何动态设置?

# 获取最大内存:
config get maxmemory

# 设置最大内存:
config set maxmemory 1GB

8.Redis 内存溢出控制

  当 Redis 所用内存达到 maxmemory 上限时,会出发相应的溢出策略。

9.Redis 内存溢出策略

  • noeviction(默认策略):拒绝所有写入操作并返回客户端错误信息(error) OOM command not allowed when used memory,只响应读操作。
  • volatile-lru:根据 LRU 算法删除设置了超时属性(expire)的键,直到腾出足够空间为止。如果没有可删除的键对象,回退到noeviction策略。
  • allkeys-lru:根据 LRU 算法删除键,不管数据有没有设置超时属性, 直到腾出足够空间为止。
  • allkeys-random:随机删除所有键,直到腾出足够空间为止。
  • volatile-random:随机删除过期键,直到腾出足够空间为止。
  • volatile-tth 根据键值对象的 ttl 属性,删除最近将要过期数据。如果没有,回退到 noeviction 策略。

10.Redis 高可用方案

  RedisSentinel(哨兵)能自动完成故障发现和转移。

  哨兵功能比单纯的主从架构全面,它具备自动故障转移、集群监控、消息通知等功能。

  哨兵可以同时监视多个主从服务器,并且在被监视的master下线时,自动将某个slave提升为master,然后由新的master继续接收命令。整个过程如下:

  1. 初始化 sentinel,将普通的 redis 代码替换成 sentinel 专用代码
  2. 初始化 masters 字典和服务器信息,服务器信息主要保存 ip:port,并记录实例的地址和 ID
  3. 创建和 master 的两个连接,命令连接和订阅连接,并且订阅 sentinel:hello 频道
  4. 每隔 10 秒向 master 发送 info 命令,获取 master 和它下面所有 slave 的当前信息
  5. 当发现 master 有新的 slave 之后,sentinel 和新的 slave 同样建立两个连接,同时每个 10 秒发送 info 命令,更新 master 信息
  6. sentinel 每隔 1 秒向所有服务器发送 ping 命令,如果某台服务器在配置的响应时间内连续返回无效回复,将会被标记为下线状态
  7. 选举出领头 sentinel,领头 sentinel 需要半数以上的 sentinel 同意
  8. 领头 sentinel 从已下线的的 master 所有 slave 中挑选一个,将其转换为 master
  9. 让所有的 slave 改为从新的 master 复制数据
  10. 将原来的 master 设置为新的 master 的从服务器,当原来 master 重新回复连接时,就变成了新 master 的从服务器

sentinel 会每隔 1 秒向所有实例(包括主从服务器和其他 sentinel)发送 ping 命令,并且根据回复判断是否已经下线,这种方式叫做主观下线。当判断为主观下线时,就会向其他监视的 sentinel 询问,如果超过半数的投票认为已经是下线状态,则会标记为客观下线状态,同时触发故障转移。

11.Redis 集群方案

  Twemproxy、Redis Cluster、Codis。

  如果说依靠哨兵可以实现 redis 的高可用,如果还想在支持高并发同时容纳海量的数据,那就需要 redis 集群。redis集群是 redis 提供的分布式数据存储方案,集群通过数据分片 sharding 来进行数据的共享,同时提供复制和故障转移的功能。

一个redis集群由多个节点 node 组成,而多个 node 之间通过 cluster meet 命令来进行连接,节点的握手过程:

  1. 节点A收到客户端的 cluster meet 命令
  2. A 根据收到的 IP 地址和端口号,向 B 发送一条 meet 消息
  3. 节点 B 收到 meet 消息返回 pong
  4. A 知道 B 收到了 meet 消息,返回一条 ping 消息,握手成功
  5. 最后,节点 A 将会通过 gossip 协议把节点 B 的信息传播给集群中的其他节点,其他节点也将和 B 进行握手

12.RedisCluster 槽

  范围:0~16383

  redis 通过集群分片的形式来保存数据,整个集群数据库被分为 16384 个槽,集群中的每个节点可以处理 0-16384 个槽,当数据库16384个槽都有节点在处理时,集群处于上线状态,反之只要有一个槽没有得到处理都会处理下线状态。通过 cluster addslots 命令可以将槽指派给对应节点处理。

  槽是一个位数组,数组的长度是 16384/8=2048,而数组的每一位用 1 表示被节点处理,0 表示不处理,如图所示的话表示 A 节点处理 0-7 的槽。

  当客户端向节点发送命令,如果刚好找到槽属于当前节点,那么节点就执行命令,反之,则会返回一个 MOVED 命令到客户端指引客户端转向正确的节点。(MOVED 过程是自动的)

  如果增加或者移出节点,对于槽的重新分配也是非常方便的,redis 提供了工具帮助实现槽的迁移,整个过程是完全在线的,不需要停止服务。

13.Redis 锁实现思路

  • setnx(set if not exists),如果创建成功则表示获取到锁。
  • setnxlock true 创建锁
  • dellock 释放锁

  如果中途崩溃,无法释放锁?此时需要考虑到超时时间的问题。比如 :expire lock 300。由于命令是非原子的,所以还是会死锁,如何解决?Redis支持 set 并设置超时时间的功能。比如: set lock true ex 30 nx。

14.布隆过滤器

  是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。

  Tips:当判断一定存在时,可能会误判,当判断不存在时,就一定不存在。

 

 

 

 

 

 

参考:https://mp.weixin.qq.com/s?__biz=MzA5MzY4NTQwMA==&mid=2651019247&idx=3&sn=806af61723b1eee62fb463b9110bed49

 

posted @ 2020-06-12 00:14  ''竹先森゜  阅读(1439)  评论(0编辑  收藏  举报