Redis中间件(从搭建到弃坑)

Redis

  • 1.Redis到底是单线程还是多线程
  • 2.Redis单线程为什么会这么快
  • 3.Redis底层数据是如何用跳表来存储的
  • 4.Redis的持久化机制
    • RDB
    • AOF
  • 5.Redis的过期key删除策略
  • 6.Redis集群方案
    • 哨兵模式
    • Redis Cluster
  • 7.缓存击穿、缓存穿透、缓存雪崩
    • 缓存击穿
    • 缓存穿透
    • 缓存雪崩
  • 8.Redis分布式锁实现
  • 9. Redis主从复制的核心原理

1.Redis到底是单线程还是多线程

    Redis6.0之前的单线程是指网络IO和键值对读写时一个线程来完成。
    Redis6.0之后引入的多线程是指网络请求过程采用了多线程,而键值对读写的命令仍然是单线程处理的,所以Redis是并发安全的

    也就是说,只有网络请求模块和数据操作模块是单线程的,而其他的持久化、集群数据同步等是多线程的。
Redis中间件(从搭建到弃坑)_第1张图片

2.Redis单线程为什么会这么快

  1. 命令执行是基于内存操作的,一条命令在内存里操作的时间只有几十纳秒。
  2. 命令的执行是单线程操作,没有线程切换的开销。
  3. 基于IO多路复用机制,来提升Redis的IO利用率。
  4. 高效的数据结构,全局hash表以及多种高效的数据结构。比如跳表,压缩列表等。

3.Redis底层数据是如何用跳表来存储的

    Redis的数据结构有一个Zset,是一个有序集合,它的数据结构是压缩列表或者跳表

    跳表,存储有序元素的时候,是把元素都放入到链表中,然后按照有序集合里面元素的分值从小到大,从左到右进行排序。链表的插入元素是比较快的。
    将有序链表改造为支持近似“折半查找”的算法,可以快速的插入、删除、查找。
Redis中间件(从搭建到弃坑)_第2张图片

4.Redis的持久化机制

    Redis的持久化有两种,一种是RDB,一种是AOF。

RDB

将某一刻的内存快照,以二进制的方式写入磁盘。

手动触发:

  1. save命令,使用Redis处于阻塞状态(指的是redis的主进程),直到RDB持久化完成,才会响应其他客户端发来的命令,我们的读写请求都会等待RDB完成。所以在生产环境一定要慎用。
  2. bgsave命令,通过主进程fork出一个子进程执行持久化,主进程只在fork过程中有短暂的阻塞,子进程再被创建后,主进程就可以响应客户端的请求了。主进程的写时拷贝策略来保证父子进程的数据共享,把父进程写的命令拷贝出一个副本,在副本中修改这个数据。此时子进程读的数据还是原来的数据。

自动触发

  1. save m n :在m秒内,如果有个键发生改变则自动出发持久化,通过bgsave执行
  2. flushall :用于清空redis所有数据库,flushdb清空当前redis所在库数据,会清空RDB文件。
  3. 主从同步:全量同步时会自动触发bgsave命令,生成rdb发送给从节点。

优点:

  1. 整个redis数据库只包含一个文件 dump.rdb,方便持久化
  2. 容灾性好,方便备份
  3. 性能最大化,fork子进程来完成写操作,让主进程继续处理命令,所以IO最大化。
  4. 相对于数据集较大时,比AOF的启动效率高。

缺点:

  1. 数据安全性低,RDB是间隔一段时间进行持久化,如果持久化之间redis,会导致数据丢。
  2. 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至1秒。

AOF

    以日志的形式记录服务器锁处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作 记录,调操作系统命令进程刷盘。RDB保存的是数据,AOF保存的是增删改查指令。

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

同步策略

  1. 每秒同步:异步完成,效率非常高,一旦出现宕机,那么一秒中内修改的数据会丢失。
  2. 每修改同步,同步持久化,每次发生的数据变化都会被立刻记录到磁盘中,最多丢失一条。
  3. 不同步,有操作系统控制,可能丢失较多的数据。

优点:

  1. 数据安全
  2. 通过append模式写文件,即使中途服务器宕机也不会破坏已存在文件的内容,可以通过redis-check-aof工具解决数据一致性问题
  3. AOF机制rewirte模式。定期对AOF文件进行重写,以达到压缩的目的。

缺点:

  1. AOF文件比RDB文件大,且恢复速度慢
  2. 数据集较大的时候,比rdb启动效率慢
  3. 运行效率没RDB高

5.Redis的过期key删除策略

    Redis是key-value数据库,我们可以设置Redis中缓存的key的过期时间。Redis的过期就是指当Redis中缓存的ey过期了,Redis如何处理。

惰性过期:只有当访问一个key时,才会判断key是否已过期,过期则清除。虽然该策略可以最大化节省CPU资源,但是对内存的压力非常大。极端情况下可能出现大量的过期key没有再被访问,不清除,占用大量内存

定期过期:每隔一段时间会扫描一定数量的数据库的expires中字典一定数量的key,并清除其中已过期的key。这种策略是一种折中方案,使CPU和内存资源达到最优的平衡效果。

Redis同时使用了惰性过期和定时过期两种过期策略。

6.Redis集群方案

哨兵模式

    哨兵模式是主从模式的升级。哨兵是redis集群中一个非常重要的组件,主要的功能如下

  • 集群监控:负责监控redis的主节点和从节点是否工作正常。
  • 消息通知:如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员。
  • 故障专业:如果主节点挂了,会自动转移到从节点上。
  • 配置中心:如果故障转移发生了,通知管理员。

哨兵用于实现redis集群的高可用,本身也是分布式,也可以做集群。作为一个哨兵集群去运行,互相协同工作。
特点:

  • 故障转移时,判断一个主节点是否宕机了(判断主节点是主观下线的还是客观下线的),会存在两种判断,需要大部分哨兵都同意才行,涉及到了分布式选举。
  • 即使部分哨兵节点挂了,哨兵集群还是能正常工作的。
  • 哨兵通常需要3个+,保证自身的健壮性。
  • 哨兵+redis主从的部署架构,是不能够保证数据的丢失问题,只能保证redis集群的高可用性。

Redis Cluster

    Redis Cluster是服务端的一种分辨技术。3.0版本后开始正式提供。采用slot(槽)的概念,一共分成16384个槽。redis连接的任意一个节点,都会把这个请求发送到正确的节点上执行。
    redis集群上有多少个节点,这个槽就分布在这些节点上,组成一个,这些节点互相提供服务,所谓的主从也是互为主从。
    比如说上面有5000个槽位,比如说有一个节点a是从节点,这个a节点会复制这5000个槽位在这个节点上面,这是主从,保证数据的安全性。这个a节点同时又是主节点,除了备份其他的5000个节点上,自己本身还有5000个槽位,这些5000个槽位又是其他节点来提供备份。

  • 通过哈希的方式,将数据分片,将key均匀的分散到每个槽上,再来判断槽在那个节点上。
  • 每份数据分会存储在互为主从的多个节点上。
  • 数据先写入主节点,再同步到从节点。
  • 同一分片的数据的多个节点不保证强一致性。
  • 读数据时,当客户操作的key没有分配在该节点上,redis会转向指令,指向正确的节点。
  • 扩容时需要把旧节点的数据迁移一部分到新节点上。

优点:

  • 无中心架构,支持动态扩容,对业务透明。
  • 具备哨兵的监控和自动的故障转移能力。
  • 客户端不需要连接集群中的所有节点,连接一个可用的即可
  • 高性能。

缺点:

  • 运维也很复杂,因为扩容需要移动槽
  • 只能使用redis中的0号数据库(redis中有11个数据库)
  • 不支持批量操作
  • 分布式逻辑和存储模块耦合等。

7.缓存击穿、缓存穿透、缓存雪崩

缓存击穿

    缓存击穿是指缓存中没有但数据库有的数据(一般都是缓存过期)。这时由于并发用户太多,同时读缓存没读到数据,又去数据库读取,引起数据库压力增加。和雪崩不同的是,击穿只是并发的查找一个数据,雪崩是不同的过期了。

解决方案

  1. 设置热点数据永不过期
  2. 加互斥锁,与雪崩的效果一样。

缓存穿透

    缓存穿透是指缓存和数据库中都没有数据,导致所有的请求都落在数据库上,导致数据库短时间内承受大量请求而崩掉。缓存穿透一般来自恶意攻击。

解决方案

  1. 接口层增加校验,如用户权限校验,id做基础校验,比如id<=0
  2. 从缓存中取不到数据,在数据库中也没取到,这时可以将key - value存为null,那么针对这同一个key的攻击就无效。
  3. 布隆过滤器。

缓存雪崩

    缓存雪崩是指缓存同一时间大面积失效,所以后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。

解决方案

  1. 缓存数据的过期时间随机设置,防止同一时间内大量数据过期的现象发生。
  2. 给每一个缓存数据增加响应的缓存标记,记录缓存是否失效,如果失效了,就更新缓存数据,但是比较耗费CPU性能。
  3. 缓存预热,把热点数据先放到缓存中,在开启服务器。
  4. 互斥锁,查数据库时,把缓存的键锁起来,其他同一key的请求阻塞,然后等第一个查出来后,在放到缓存中其他阻塞的请求再去从缓存中拿。

8.Redis分布式锁实现

  1. 首先利用setnx来保证:如果key不存在才能获取到锁,如果key存在,则获取不到锁。
  2. 然后还要利用lua脚本来保证多个redis操作的原子性
  3. 同时还要考虑到锁过期,所以需要额外的一个看门狗定时任务来监听锁是否需要续约。
  4. 同时还要考虑到redis节点挂掉后的情况,所以需要采用红锁的方式来同时向N/2+1个节点申请锁,都申请到了才证明获取锁成功,这样就算其中某个redis节点挂掉了,锁也不能被其他客户端获取到。

9. Redis主从复制的核心原理

  1. 集群启动时,主从车间会先建立连接,为全量复制做准备
  2. 主库将所有数据同步给从库。从库收到数据后,在本地完成数据加载,这个过程依赖于内存快照RDB
  3. 在主库将数据同步给从库的过程中,主库不会阻塞,仍然可以正常接收请求。否则,redis的服务就被中断了。但是,这些请求中的写操作并没有记录到刚刚生成的RDB文件中。为了保证主从库的数据一致性,主库会在内存中用专门的replication buffer,记录RDB文件生成收到的所有写操作。
  4. 最后,也就是第三个阶段,主库会把第二阶段执行过程中新收到的写命令,再发送给从库。具体的操作是,当主库完成RDB文件发送后,就会把此时replocation buffer中修改操作发送给从库,从库再执行这些操作。这样一来,主从库就实现同步了。
  5. 后续主库和从库都可以处理客户端读操作,写操作只能交给主库处理,主库接收到写操作后,还会将写操作发送给从库,实现增量同步

你可能感兴趣的:(Redis,redis,中间件,java)