自己怎么做装修网站,网站建设设计岗位职责,河南省水利建设管理处网站,上海湖南网站建设淘汰策略
只有 redis 内存空间已满并且往里面写新数据#xff0c;才会触发淘汰策略。通过 expire / / /pexpire 让 key-value 过期#xff0c;从而让 redis 清除这个 key-value。value 的数据结构typedef struct redisObject {unsigned tpye:4;unsigned encoding:4;// 判断哪…淘汰策略
只有 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 建立连接否则无法线上新增 replicareplica 主动向 master 拉取数据若网络出现问题replica 持有同步位置复制偏移量缺点可能带来数据不一致某一时刻如果从 replica 中获取数据数据可能不是最新的。 实现 master 记录了一个环形缓冲区和一个复制偏移量replica 记录了一个复制偏移量。RUN ID 无论 master 还是 replica 都有自己的 RUN IDRUN ID 在其启动时自动产生由 40 个随机的十六进制字符组成。当 replica 对 master 初次复制时master 将自身的 RUN ID 发送给 replicareplica 会将 RUN ID 保存当 replica 断线重连 master 时replica 将向 master 发送之前保存的 RUN ID。如果 replica RUN ID 和 master RUN ID 一致说明 replica 断线前复制的就是当前的 mastermaster 尝试执行增量更新。若不一致说明 replica 断线前复制的 master 并不是当前的 master则 master 将对 replica 执行全量更新。 复制偏移量 offset64 位的整数且一直累加 master 和 offset 都会维护一个复制偏移量master 向 replica 发送 N 个字节的数据时将自己的复制偏移量加上 Nreplica 接收到 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 180000cluster 集群 实现高可用 数据备份每个主节点都会有多个从节点。主节点转移集群节点间会互相发送消息交换节点的状态信息若某主节点下线将会被其它节点标记下线接着在该下线主节点的从节点中选择一个数据最新的从节点作为主节点从节点继承下线主节点的槽位信息并广播改消息给集群中的其它节点。 特征 去中心化没有中心节点。主节点对等。能够进行数据扩容。读写数据只会通过主节点进入集群。 流程 连接集群中任意一个节点。若数据不在该节点将收到连接切换的命令继而连接到目标节点。 缺点因为主从采用异步复制在主节点转移时仍存在数据丢失的情况。配置集群
# 创建 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