Redis 淘汰策略、持久化、高可用

淘汰策略

  • 只有 redis 内存空间已满并且往里面写新数据,才会触发淘汰策略
  • 通过 expire / / /pexpire 让 key-value 过期,从而让 redis 清除这个 key-value。
  • value 的数据结构
    typedef struct redisObject {
    	unsigned tpye:4;
    	unsigned encoding:4;
    	
    	// 判断哪些 key 要被删除
    	unsigned lru:LRU_BITS; // 占用 24位,8位用来记录访问的次数(0-255次),16位用来记录上一次访问的时间
    	
    	int refcount; // 引用计数
    	void *ptr; // 指向 value 的存储空间
    } robj;
    
    object idletime key # 展示 value 的 lru 字段
    
  • 配置淘汰策略
    • 如果 redis 内存空间已满,并且没有设置淘汰策略,再 set key value 会直接返回错误,提示内存空间已满;如果设置了淘汰策略,redis 会按照淘汰策略选择数据进行删除,再 set key value 就会成功。
      # redis.conf
      maxmemory <bytes>  # redis 最多可以使用多少空间
      maxmemory-policy   # 淘汰策略,默认为 noeviction, 不进行淘汰
      maxmemory-samples  # 默认为 5,选择多少个 key 进行淘汰
      
    • 过期 key 中
      • volatile-lru:最长时间没有使用。
      • volatile-lfu:最少次数使用,随机采样。
      • volatile-ttl:最近要过期。
      • volatile-random:随机。
    • 所有 key
      • allkeys-lru。
      • allkeys-lfu 。
      • allkeys-random 。
    • 禁止淘汰:no-eviction。

持久化

  • redis 为什么需要持久化 ?
    • 因为 redis 是内存数据库,一旦关闭,内存中的数据就丢失了,所以需要把内存中的数据写到磁盘中,这样 redis 重启后就可以从磁盘中加载原来的数据到内存中。
    • 只有写操作(增删改操作,会引起数据库变更的操作)才会进行持久化。
  • redis 持久化方式
    • aof
      • 持久化的是写操作协议内容(通过重放恢复内存中的数据),会有很多冗余数据;在 redis 进程中完成,every_sec 会另启线程做持久化。
        *3
        $3
        set
        $4
        mark
        $1
        2
        
      • 策略
        • no:关闭 aof。
        • always:先将数据持久化到磁盘,再响应客户端。(效率很低,一般不采用)
        • every_sec:只要内存修改成功,立刻响应客户端。
          • 先将数据写到 aof buffer 中,一秒后将 aof buffer 中的数据持久化到磁盘,这个过程是异步的,使用 bio_fsync_aof。
        • always 和 every_sec 会调用 fsync(fd) 将 page cache 中的数据立刻持久化到磁盘。 在这里插入图片描述
      • aof-rewrite
        • 因为 aof 文件过大,数据恢复速度太慢,所以要减少 aof 文件大小。
        • 工作原理
          • fork 进程,根据内存数据生成 aof 文件,避免同一个 key 的历史冗余数据。
          • 在重写 aof 期间,对 redis 的写操作会被记录到重写缓冲区,在重写 aof 结束后,再将这些写操作附加到 aof 文件末尾(可能有冗余数据)。
    • rdb
      • 持久化的是二进制数据(根据磁盘中的二进制数据恢复内存中的数据);另启进程做持久化。
      • 工作原理:通过 fork 子进程进行持久化,基于内存中对象编码直接持久化。
        • fork 相当于给父进程的内存做了一个快照。
        • fork 写时复制
          在这里插入图片描述
          • 页表存储了虚拟内存和物理内存之间的映射关系。
          • linux 为了加快 fork 的流程,fork 仅仅会复制页表,然后将两个页表中的所有保护位修改为只读,此时父进程和子进程共用一块物理内存;父进程依然对外提供服务。
          • 当父进程处理写操作时,首先会找到虚拟内存的内存页,然后通过页表写物理内存页的时候,发现保护位是只读的,此时会触发写保护中断:在物理内存中完成一次物理页复制(把原来的物理页复制一份),然后把数据写入到复制后物理页中,最后在写保护中断的处理函数中将页表中的保护位修改为可读可写,并且重新构建页表中的映射关系(页表中该虚拟内存的指向变为新的物理页)。
      • rdb-aof 混用
        • 通过 fork 子进程,根据内存数据生成 rdb 文件。
        • 在 rdb 持久化期间,对 redis 的写操作会被记录到重写缓冲区,在 rdb 持久化结束后,采用 aof 的方式附加到文件末尾。
  • redis 持久化方式优缺点
    • aof
      • 优点:数据可靠,丢失较少;持久化过程代价较低(是顺序磁盘 IO,持久化速度快)。
      • 缺点:aof 文件过大,数据恢复慢(通过重放恢复内存中的数据)。
    • rdb
      • 优点:rdb 文件小,数据恢复快。
      • 缺点:数据丢失较多;持久化过程代价较高。
  • 大 key 问题:kv 中,value 如果占用大量空间就是大 key,比如 value 是 hash、zset,里面存储大量元素。
    • fsync 压力大。
    • 因为页表大,所以 fork 时间长,写时复制造成持久化时间长。

高可用

  • 为什么实际业务中有高可用的需求 ?
    • 比如服务器依赖 redis,如果 redis 宕机了,那么服务器就不能给客户端响应了,此时整个服务器处于不可用状态。
    • redis 高可用:如果 redis 中的一个节点宕机了,会有备用节点顶替它,服务器不会因为 redis 中的一个节点宕机了,造成服务不可用。
  • 什么是高可用 ?
    • 在合理的时间内给出合理的回复。
      • 合理的时间:秒级的。
      • 合理的回复:给一个请求,如果发生错误,需要回复是到底是什么错误,不能模棱两可。
  • 如何实现高可用 ?
    • 数据备份。
    • 节点切换策略。

主从复制

  • 主从复制不能保证高可用,只起到了数据备份的作用。
  • 含义
    • 主从复制是异步复制,服务器写数据到主数据库(master),主数据库立刻返回;从数据库(replica)不断地从主数据库中拉取数据并保存,以达到从数据库和主数据库数据一致。
    • replica 主动向 master 建立连接(否则无法线上新增 replica)
    • replica 主动向 master 拉取数据(若网络出现问题,replica 持有同步位置:复制偏移量)
    • 缺点:可能带来数据不一致:某一时刻如果从 replica 中获取数据,数据可能不是最新的。
  • 实现
    在这里插入图片描述
    在这里插入图片描述
    • master 记录了一个环形缓冲区和一个复制偏移量,replica 记录了一个复制偏移量
    • RUN ID:
      • 无论 master 还是 replica 都有自己的 RUN ID,RUN ID 在其启动时自动产生,由 40 个随机的十六进制字符组成。
      • 当 replica 对 master 初次复制时,master 将自身的 RUN ID 发送给 replica,replica 会将 RUN ID 保存;当 replica 断线重连 master 时,replica 将向 master 发送之前保存的 RUN ID。
      • 如果 replica RUN ID 和 master RUN ID 一致,说明 replica 断线前复制的就是当前的 master,master 尝试执行增量更新。若不一致,说明 replica 断线前复制的 master 并不是当前的 master,则 master 将对 replica 执行全量更新
    • 复制偏移量 offset(64 位的整数且一直累加):
      • master 和 offset 都会维护一个复制偏移量;master 向 replica 发送 N 个字节的数据时,将自己的复制偏移量加上 N,replica 接收到 master 发送的 N 个字节的数据时,将自己的复制偏移量加上 N。
      • 如果 replica 记录的复制偏移量在环形缓冲区中,就将 master 中的数据偏移和 replica 的数据偏移之间的数据发给 replica(增量更新)。
      • 如果 replica 记录的复制偏移量不在环形缓冲区中,就把 master 中的 rdb 数据发给 replica(全量更新)。
      • 通过比较主从偏移量得知主从之间数据是否一致;偏移量相同则数据一致,偏移量不同则数据不一致。
      • 复制偏移量越大,数据越新

哨兵模式

在这里插入图片描述

  • 哨兵模式是 redis 高可用的解决方案:
    • 由一个或多个 sentinel 实例构成 sentinel 集群,该集群可以监视任意多个主库以及这些主库所属的从库;当主库处于下线状态,会自动将该主库所属的某个数据最新的从库升级为新的主库。
    • 客户端连接集群时,首先会连接 sentinel(任意一个 sentinel),通过 sentinel 来查询主库的地址(ip 地址 + 端口),并且通过 subscribe 监听主库切换,然后再连接主库进行数据交互。
    • 当主库发生故障时,sentinel 会主动推送新的主库地址。这样客户端无须重启即可自动完成节点切换。
  • 检测异常
    • 主观下线:sentinel 会以每秒一次的频率向所有节点(其他 sentinel、主节点、从节点)发送 ping 消息,然后通过接收返回判断该节点是否下线;如果配置指定了 down-after-milliseconds,则在该时间内没有返回就被判断为主观下线。
    • 客观下线:当一个 sentinel 节点将一个主节点判断为主观下线之后,为了确
      认这个主节点是否真的下线,它会向其他 sentinel 节点进行询问,如果收到一定数量(半数以上)的已下线回复,sentinel 会将主节点判定为客观下线,并通过领头 sentinel 节点对主节点执行故障转移。
    • 故障转移:
      • 从节点中选举一个节点作为新的主节点(选复制偏移量最大的从节点)。
      • 通知其他从节点复制连接新的主节点。
      • 若故障主节点重新连接,将作为新的主节点的从节点。
  • 缺点:
    • 延迟较大:redis 采用异步复制的方式,意味着当主节点挂掉时,从节点可能没有收到全部的同步消息,这部分未同步的消息将会丢失。如果主从延迟特别大,那么丢失可能会特别多。
    • 不能进行数据扩容
    • 部署麻烦。
  • 配置
    # sentinel.cnf
    # sentinel 只需指定检测主节点就行了,通过主节点自动发现从节点
    sentinel monitor mymaster 127.0.0.1 6379 2
    # 判断主观下线时长
    sentinel down-after-milliseconds mymaster 30000
    # 指定可以有多少个 redis 服务同步新的主机,一般而言,这个数字越小同步时间越长; 越大,则对网络资源要求越高
    sentinel parallel-syncs mymaster 1
    # 指定故障切换允许的毫秒数,超过这个时间,就认为故障切换失败,默认为 3分钟
    sentinel failover-timeout mymaster 180000
    

cluster 集群

在这里插入图片描述

  • 实现高可用
    • 数据备份:每个主节点都会有多个从节点。
    • 主节点转移:集群节点间会互相发送消息,交换节点的状态信息;若某主节点下线,将会被其它节点标记下线,接着在该下线主节点的从节点中选择一个数据最新的从节点作为主节点;从节点继承下线主节点的槽位信息,并广播改消息给集群中的其它节点。
  • 特征:
    • 去中心化:没有中心节点。
    • 主节点对等。
    • 能够进行数据扩容。
    • 读写数据只会通过主节点进入集群。
  • 流程:
    1. 连接集群中任意一个节点。
    2. 若数据不在该节点,将收到连接切换的命令,继而连接到目标节点。
  • 缺点:因为主从采用异步复制,在主节点转移时仍存在数据丢失的情况。
  • 配置集群 在这里插入图片描述
# 创建 6 个文件夹
mkdir -p 7001 7002 7003 7004 7005 7006
cd 7001
vi 7001.conf

# 7001.conf 中的内容如下
pidfile "/home/zcoder/redis-cluster/7001/7001.pid"
logfile "/home/zcoder/redis-cluster/7001/7001.log"
dir /home/zcoder/redis-cluster/7001/
port 7001
daemonize yes
cluster-enabled yes
cluster-config-file nodes-7001.conf
cluster-node-timeout 15000

# 复制配置
cp 7001/7001.conf 7002/7002.conf
cp 7001/7001.conf 7003/7003.conf
cp 7001/7001.conf 7004/7004.conf
cp 7001/7001.conf 7005/7005.conf
cp 7001/7001.conf 7006/7006.conf

# 查看目录结构
tree .

# 修改配置
sed -i 's/7001/7002/g' 7002/7002.conf
sed -i 's/7001/7003/g' 7003/7003.conf
sed -i 's/7001/7004/g' 7004/7004.conf
sed -i 's/7001/7005/g' 7005/7005.conf
sed -i 's/7001/7006/g' 7006/7006.conf
#!/bin/bash
# 创建启动配置 start.sh
redis-server 7001/7001.conf
redis-server 7002/7002.conf
redis-server 7003/7003.conf
redis-server 7004/7004.conf
redis-server 7005/7005.conf
redis-server 7006/7006.conf
# 增加可执行权限
chmod +x start.sh 

# 启动全部 redis 节点 
./start.sh
# 查看 redis 节点是否全部启动
ps aux | grep redis-server

# 智能创建 redis 集群
# --cluster-replicas: 一个主节点对应几个从节点
redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 --cluster-replicas 1

在这里插入图片描述

# 读写数据只会通过主节点进入集群
# 进入指定的 redis 节点
redis-cli -c -p 7006 # 127.0.0.1:7006
set zcoder 1         # 会重定向到存储该数据的主节点
# 主节点宕机
redis-cli -p 7001 shutdown
# 主节点重启
redis-server 7001/7001.conf
  • 使用 crc16(zcoder) % 16384,通过增大样本数,让各个主节点存储的数据量较为均衡。
    在这里插入图片描述
  • 扩容:先增加节点,再分配槽位。
    cp -R 7001 7007
    cd 7007
    mv 7001.conf 7007.conf
    rm 7001.log dump.rdb nodes-7001.conf
    sed -i "s/7001/7007/g" 7007.conf
    cp -R 7007 7008
    cd 7008
    mv 7007.conf 7008.conf
    sed -i "s/7007/7008/g" 7008.conf
    cd ..
    redis-server 7007/7007.conf
    redis-server 7008/7008.conf
    # 7007 是主节点,7008 是从节点
    redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7001 
    redis-cli --cluster add-node 127.0.0.1:7008 127.0.0.1:7001 --cluster-slave --cluster-master-id 主节点的id
    
    # 将槽位重新分配到整个集群的所有节点中
    redis-cli --cluster reshard 127.0.0.1:7001
    How many slots do you want to move (from 1 to 16384)? #1000
    What is the receiving node ID? # 主节点的id
    Please enter all the source node IDs.
    Type 'all' to use all the nodes as source nodes for the hash slots.
    Type 'done' once you entered all the source nodes IDs.
    Source node # all
    
    # 将节点 A 的槽位迁移到节点 B
    redis-cli --cluster reshard 127.0.0.1:7001 --cluster-from 节点A的id --cluster-to 节点B的id --cluster-slots 1000
    
  • 缩容:先移动槽位,再删除节点
    redis-cli --cluster reshard 127.0.0.1:7001 --cluster-from 节点B的id --cluster-to 节点A的id --cluster-slots 1000
    # 删除节点 7007
    redis-cli --cluster del-node 127.0.0.1:7001 节点7007的id
    # 此时 7008 成为其他节点的从节点
    redis-cli --cluster del-node 127.0.0.1:7001 节点7008的id
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/428247.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

10个软件测试的吐槽点!

问题一&#xff1a;测试时间评估 这是一个工作日常经常需要回复的问题&#xff0c;理论上&#xff0c;测试这边要做出较科学合理的回复&#xff0c;那就要将【需求变更】、【开发进度延误】、【bug 修复不稳定】、【复杂业务流程】、【测试环境不稳定】、【上下游服务依赖】、…

LaTeX文档中文显示错误解决办法

LaTeX文档中文显示错误解决办法 如果在LaTeX文档中遇到中文显示错误&#xff0c;通常是因为文档没有正确配置以支持中文。解决这个问题的一个常见方法是使用XeLaTeX引擎编译文档&#xff0c;它天然支持UTF-8编码&#xff0c;可以很好地处理中文。同时&#xff0c;使用ctex宏包…

Vue3中使用ffmpeg.wasm进行转码

一、安装方法 1.1 使用yarn进行安装 yarn add ffmpeg/ffmpeg ffmpeg/core1.2 安装版本 注意安装版本需在0.12.0以上版本才可以使用下面代码&#xff08;目前更新到0.12.10&#xff09;&#xff0c;之前的版本代码使用方法有所不同&#xff08;0.12.10之后的版本也可能会有变动…

链表相加(二)

题目 题目链接 链表相加(二)_牛客题霸_牛客网 题目描述 代码实现 class Solution { public:/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可** * param head1 ListNode类 * param head2 ListNode类 * return ListNode…

4G/5G执法记录仪、智能安全帽走国标GB28181接入海康、宇视等大平台,也可走平台与平台对接,以下级平台级联到上级大平台

AIoT万物智联&#xff0c;智能安全帽生产厂家&#xff0c;执法记录仪生产厂家&#xff0c;智能安全帽、智能头盔、头盔记录仪、执法记录仪、智能视频分析/边缘计算AI盒子、车载DVR/NVR、布控球、智能眼镜、智能手电、无人机4G补传系统等统一接入大型融合通信可视指挥调度平台VM…

【算法分析与设计】被围绕的区域

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 题目 给你一个 m x n 的矩阵 board &#xff0c;由若干字符 X 和 O &#xff0c;找到所有被 X 围绕的区域&#xff0c;并将这些区域里所有…

告别手动填写邀请码,这款App数据统计工具帮你轻松实现

在移动互联网时代&#xff0c;App的推广和运营已成为各大企业的必修课。然而&#xff0c;面对错综复杂的推广渠道和浩如烟海的数据&#xff0c;如何精准地追踪用户来源、优化推广策略&#xff0c;一直是困扰着运营者的难题。今天&#xff0c;我们就来聊聊一款能够帮助你轻松解决…

『Linux从入门到精通』第 ㉓ 期 - 管道

文章目录 &#x1f490;专栏导读&#x1f490;文章导读&#x1f427;进程间通信的目的&#x1f427;如何进行进程间通信&#x1f427;进程间通信的分类&#x1f427;管道&#x1f426;什么是管道&#x1f426;管道原理 &#x1f427;实例代码&#x1f427;管道的特点&#x1f4…

如何扫码查看图片信息?图片放到二维码展示的在线教学

现在通过扫码来查看物品图片是很常用的一种方式&#xff0c;将物品不同角度的图片存入一张二维码后&#xff0c;用户只需要扫描这张二维码图片&#xff0c;就可以了解物品预览图及其他信息。常用的图片格式比如jpg、png、gif都可以放到二维码中显示&#xff0c;那么具体该怎么做…

FreeCAD|建模常用命令

import FreeCAD as App import Part 1、创建点 V1 App.Vector(0, 10, 0) 2、创建线段 L1 Part.LineSegment(V1, V2) 3、创建圆弧 C1 Part.Arc(V1, VC1, V4) 4、创建Shape S1 Part.Shape([C1, L1, C2, L2]) 5、创建基本形状 makeBox(l, w, h, [p, d]) makeCircl…

C语言:qsort的使用方法

目录 1. qsort是什么&#xff1f; 2. 为什么要使用qsort 3. qsort的使用 3.1 qsort的返回值和参数 3.2 qsort的compare函数参数 3.3 int类型数组的qsort完整代码 4. qsort完整代码 1. qsort是什么&#xff1f; qsort中的q在英语中是quick&#xff0c;快速的意思了&#…

LeetCode_Java_动态规划系列(3)(题目+思路+代码)

338.比特位计数 给你一个整数 n &#xff0c;对于 0 < i < n 中的每个 i &#xff0c;计算其二进制表示中 1 的个数 &#xff0c;返回一个长度为 n 1 的数组 ans 作为答案。 class Solution {public int[] countBits(int n) {/** 思路&#xff1a;* 1.创建一个长度为 n…

智慧市容环境卫生管理信息系统建设项目初步设计参考指南

第四章项目建设方案 梳理和编制数据标准规范&#xff0c;为数据体系建设提供建设指导。数据标准规范体系是根据统一市容环卫基础数据资源建立的&#xff0c;从要素分类、编码、符号、制图、更新机制等层 面解决各类规划标准不衔接、各自为政问题。标准规范体系包括&#xff1…

回溯难题(算法村第十八关黄金挑战)

复原 IP 地址 93. 复原 IP 地址 - 力扣&#xff08;LeetCode&#xff09; 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔。 例如&#xff1a;"0.1.2.201" 和 &q…

【计算机毕业设计】044学生管理系统

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

数据结构——算法与算法分析3,4

目录 1.分析算法时间复杂度的方法 举例&#xff1a; 1.数据集队时间复杂度的影响 2.空间复杂度 3.设计好算法的过程 1.分析算法时间复杂度的方法 举例&#xff1a; 1.数据集队时间复杂度的影响 一般只考虑最坏时间复杂度和平均时间复杂度 2.空间复杂度 3.设计好算法的过程…

【Android 内存优化】怎么理解Android PLT hook?

文章目录 前言什么是hook?PLT hook作用基本原理PLT hook 总体步骤 代码案例分析方案预研面临的问题怎么做&#xff1f;ELFELF 文件头SHT&#xff08;section header table&#xff09; 链接视图&#xff08;Linking View&#xff09;和执行视图&#xff08;Execution View&…

Vue使用高德地图定位到当前位置,并显示天气信息

首先得去高德控制台申请两个 key&#xff0c;一个天气key和一个定位key 获取天气信息的函数&#xff1a; const getWeather function (city) {// 使用 fetch 发送请求获取天气信息fetch(https://restapi.amap.com/v3/weather/weatherInfo?city${city}&keyeefd36557b0250…

二,几何相交----2,区间相交检测IID--(1)算法

对于空间的线段是否相交&#xff0c;假设都是与x平行&#xff0c;则需要三步 1&#xff0c;对各线段左右端点设置为L,R标志 2&#xff0c;从小到大进行排序 3&#xff0c;线性扫描&#xff0c;从小到大&#xff0c;根据模式判断是否相交&#xff0c;假设不相交&#xff0c;则应…

【JavaScript】面试手撕浅拷贝

【JavaScript】面试手撕浅拷贝 引入 浅拷贝和深拷贝应该是面试时非常常见的问题了&#xff0c;为了能将这两者说清楚&#xff0c;于是打算用两篇文章分别解释下深浅拷贝。 PS: 我第一次听到拷贝这个词&#xff0c;有种莫名的熟悉感&#xff0c;感觉跟某个英文很相似&#xff…