@octopus
2020-10-09T18:07:08.000000Z
字数 5325
阅读 1405
redis
面试
slowlog 是一个先进先出队列,有固定长度,保存在内存内
建议设置 1000 左右
slowlog-max-len 设置slowlog 的队列长度,默认128
建议设置 1ms
满查询阀值,设置查询时间超过 x 微秒的加入慢查询队列,默认10000
slowlog get [n] // 获取n条满查询队列中的记录
slowlog len // 获取满查询队列长度
slowlog reset // 清空满查询队列
普通一次 get set 等命令,需要一次网络连接时间,一次服务器处理时间,
n 次就要 n次网络连接时间,n次服务器处理时间
M操作(mget mset等)以及pipline管道操作等只需1次连接+n次处理时间
$redis->connect('127.0.0.1');
//不具备原子性 ,管道
$redis->pipeline();
for ($i=0;$i<100000;$i++)
{
$redis->set("test_{$i}",pow($i,2));
$redis->get("test_{$i}");
}
$redis->exec();
$redis->close();
注意,每次 pipeline 携带的数据数量不宜非常多
pipeline 只能作用在一个redis节点
pipeline 与 M操作的区别是,M操作是原子性的,pipeline 不是
如何触发快照?有三种方式:
主动触发:
* 同步 save
* 异步 bgsave
* 自动
被动触发:
* 全量复制
* debug reload
* shutdown
save 是同步阻塞的,在生成rdb文件之前所有命令都在阻塞
redis> save
ok
复杂度 O(n)
若有旧的rdb文件将被覆盖
bgsave 调用linux的fork开一个子进程,开做快照,是异步的但从开始快照后新增的数据会被丢失
设置配置项以后,当满足 每60秒内产生10000次数据变化,每300秒内有10条数据额变化,每900秒内有1条数据变化,这三种情况一种满足,则做一次快照
1. 关闭自动生成
2. dbfilename dump-${port}.rdb // 设置rdb文件名以端口号区分
3. dir /bigdiskpath // 设置快照目录到空间充足的磁盘区域
4. stop-writes-no-bgsave-error yes // 当发生错误停止做快照
5. rdbcompression yes // 压缩的方式
6. rdbchecksum yes // 采用校验和
只要有写命令,就会把命令写入 AOF 文件中,几乎是实时的
每当有一条写命名执行就立刻写入硬盘(AOF文件)
每秒把缓冲区的命令同步到硬盘(AOF文件)
操作系统决定什么时候把缓冲区的命令刷新进硬盘(AOF文件),不可控
命令 | always | everysec | no |
---|---|---|---|
优点 | 不丢失数据 | 最多丢失一秒的数据 | 不用管 |
缺点 | IO开销大,一般stat盘只有几百TPS | 同优点 | 不可控 |
由于后期AOF文件过大,所以要优化重写,将重复数据,过期数据,无用数据进行删除。
fork() 新进程来重写
配置名 | 含义 |
---|---|
suto-aof-rewrite-min-size | 触发AOF重写要达到的尺寸 |
suto-aof-rewrite-percentage | 重写后再次触发AOF重写的文件增长率 |
统计命令 | 含义 |
---|---|
aof_current_size | AOF文件当前大小(字节) |
aof_base_size | AOF上次启动或重写后的尺寸(字节) |
appendonly yes // 打开AOF
appendfilename "appendonly-${port}.aof" //保存数据的AOF文件名称
appendfsync everysec // AOF策略
dir // 存放AOF的目录
no-appendfsync-on-rewrite yes // 当出现阻塞场景,不继续写入AOF文件,将数据保留在缓冲区等待下次操作,性能优先
auto-aof-rewrite-percentage 100 // 重写后再次触发AOF重写的文件增长率
auto-aof-rewrite-min-size 64mb // 触发AOF重写要达到的尺寸
单机有什么问题?
机器故障
容量瓶颈问题
环境说明:
主从服务器在一台机器上
主服务器端口号 6379
从服务器端口号 6380
cp redis.conf redis-6379.conf
cp redis.conf redis-6380.conf
// 通用配置
daemonize yes # 守护进程方式启动
#save 900 1 # 关掉自动快照的三行
dir /xxx/data # 设置存储备份文件目录
// 主服务器配置
port 6379
logfile '6379.log'
pidfile /var/rum/redis-6379.pid
dbfilename dump-6379.rbd
// 从服务器配置
port 6380
logfile '6380 .log'
pidfile /var/rum/redis-6380.pid
dbfilename dump-6380.rbd
slaveof 127.0.0.1 6379 # 希望复制哪台主服务器
// 启动主从服务器
redis-server redis-6379.conf
redis-server redis-6380.conf
(用 ps -ef |grep redis-server 查看是否已经启动)
// 查看分片信息
info replication
通过配置,第一次主从同步,依然会用 RDB 快照的方式,进行全量复制,从服务器只可读不可写。当主服务器有数据写入,就会自动同步到从服务器。
主从节点会根据偏移量进行数据同步,当主从偏移量差距过大说明有网络问题或是阻塞等
redis-cli -p 6379 info replication // 在主节点查看偏移量信息
master_repl_offset:2048 // 当前主节点的偏移量
slave0:ip=127.0.0.1,port=6380,offset=2380 // 从服务器的偏移量
1. 从服务器向主服务器发送 PSYNC ? -1 表示不知道你的runId 也没有偏移量,表示要全量复制
2. 主服务器告诉从服务器它的 runId,以及它的偏移量
3. 从服务器保存2传来的信息
4. master 启动子进程进行 bgsave 保存一份快照,在此过程中,若有新的数据写入,则写入 real_back_buffer 缓冲区
5. 当快照完成,发送快照给从服务器
6. 并发送缓冲区中新写入的信息
7. 删掉旧数据
8. 载入RDB快照
当 master 节点发生故障,从节点就无法正常获取到数据,也无法写入数据
将从节点1作为新的 master,让从2节点从节点1复制
这个过程需要手动或着脚本监控,而 Sentinel 可以做到监控多组 master-slave,自动完成故障转移。
redis 会单独开启一个进程运行 Sentinel,Sentinel有多个客户端,来监控主从节点的“健康状态”。
client客户端会从 Sentinel 读写数据,Sentinel 知道主从信息,去正确额度读取和写入,相当于一个“中间人”的角色。
当 多个 Sentinel 发现 master 出现了故障:
1)就会选举出一个 Sentinel 作为修复的执行者;
2)选出一个 slave 从节点,作为新的 master;
3)通知其他 slave 复制新的 master;
4)通知客户端的主从变化;
5)当 master “复活”,则让它变成 slave,复制新的 master。
环境概述:
开三个 Sentinel 对主从节点进行监控
共有三个redis节点,一主两从
// sentinel 配置
// sentinel 端口号(三个各自不同)
port $(port)
// 以守护进程方式启动
daemonize yes
// 虽然不存储数据,但也要配置日志路径
dir "/opt/xxx/data/"
logfile "${port}.log"
// 当前Sentinel节点监控 127.0.0.1:6379 这个主节点,
// 2代表判断主节点失败至少需要2个Sentinel节点节点同意
// mymaster是主节点的别名
sentinel monitor mymaster 127.0.0.1 6379 2
//每个Sentinel节点都要定期PING命令来判断Redis数据节点和其余Sentinel节点是否可达,如果超过30000毫秒且没有回复,则判定不可达
sentinel down-after-milliseconds mymaster 30000
//原来的从节点会向新的主节点发起复制操作,限制每次向新的主节点发起复制操作的从节点个数为1,来减轻主节点压力
sentinel parallel-syncs mymaster 1
//故障转移超时时间为180000毫秒
sentinel failover-timeout mymaster 180000
简洁版本:
cp redis/redis-sentinel.conf redis-sentinel-26379.conf
port 26379
daemonize yes
dir "/opt/xxx/data/"
logfile 26379.log
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
// 启动 Sentinel (三个配置只是端口号,日志名不同,监听同一master)
redis-sentinel redis-sentinel-26379.conf
redis-sentinel redis-sentinel-26380.conf
redis-sentinel redis-sentinel-26381.conf
// 客户端连接 Sentinel
redis-cli -p 26379
// 查看主从信息,健康状态等
> info
// 再次查看 redis-sentinel-26379.conf
会发现多了从节点的信息
slaveof no one
命令,让它成为新主节点更新原来的 master 为从节点,保持关注,当它恢复以后命令它复制新主节点信息
如何选择合适的节点?
1. 选择 slave-priority 优先级最高的节点,若不存在则继续
2. 选择复制偏移量最大的节点,若不存在最大则继续
3. 选择 runId 最小的节点(最早的slave)