ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

redis 读写分离

2022-06-01 01:02:26  阅读:157  来源: 互联网

标签:node slave 读写 分离 redis 6379 复制 master


前言

若要搞好高并发的话,不可避免,要把底层的缓存搞好。若要做一些比如电商的商品详情页,真正的超高并发,QPS上十万甚至是百万,一秒钟百万的请求量,光是 redis 是不够的,但是 redis 是整个大型的缓存架构中,支撑高并发的架构里面,非常重要的一个环节。首先,你的底层的缓存中间件,缓存系统,必须能够支撑的起我们说的那种高并发,其次,再经过良好的整体的缓存架构设计(比如说多级缓存架构、热点缓存)

redis 不能支撑高并发的瓶颈在哪里

单机

如果 redis 要支撑超过 10万+ 并发,该怎么做?

单机的 redis 几乎不太可能说 QPS 超过10万+,除非一些特殊情况,比如说你的机器性能特别好,配置特别高,物理机,维护做到特别好,而且你的整体的操作不是太复杂
读写分离,一般来说,对缓存,一般都是用来支撑读高并发的,写的请求是比较少的,可能写请求也就是一秒钟几千,一两千,大量的请求都是读,一秒钟二十万次读

master持久化对于主从架构的安全保障的意义

图解redis replication基本原理

redis replication 的核心机制

  • redis 采用异步方式复制数据到 salve 节点,不过从 redis2.8 开始,salve node 会周期性地确认自己每次复制的数据量
  • 一个 master node 是可以配置多个 salve node 的
  • slave node 也可以连接其他的 salve node
  • slave node 做复制的时候,是不会 block master node 的正常工作
  • slave node 在做复制的时候,也不会 block 对自己的查询操作,它会用旧的数据集来提供服务;但是,复制完成的时候,需要删除旧数据集,加载新的数据集,这个时候就会暂停对外服务了
  • slave node 主要用来进行横向扩容,做读写分离,扩容的 slave node 可以提高读的吞吐量

master 持久化对于主从架构的安全保障的意义

如果采用了主从架构,那么建议必须开启 master node 的持久化,不建议用 slave node 作为 master node 的数据热备,因为那样的话,如果你关掉了 master的持久化,可能在 master 宕机重启的时候数据是空的,然后可能一经过复制,salve node 数据也丢了
若 master RDB 和 AOF 都关闭了,数据会全存在内存中,master 宕机重启,是没有本地数据可以恢复的,然后就会认为自己的数据是空的,master 就会将空的数据集同步到 salve 上去,所有 slave 的数据全部清空,100%的数据丢失

主从架构的核心原理

主从架构的核心原理

  • 当启动一个 slave node 的时候,它会发送一个 PSYNC 命令给 master node
  • 如果这是 slave node 重新连接 master node,那么 master node 仅仅会复制给 slave 部分缺少的数据;否则如果是 slave node 第一次连接 master node,那么会触发一次 full resynchronization
  • 开始 full resynchronization 的时候,master 会启动一个后台线程,开始生成一份 RDB 快照文件,同时还会将从客户端收到的所有写命令缓存在内存中。RDB 文件生成之后,master 会将这个 RDB 发送给 slave,slave 会先写入本地磁盘,然后再从本地磁盘加载到内存中,然后 master 会将内存中缓存的写命令发送给 slave,slave 也会同步这些数据
  • slave node 如果跟 master node 有网络故障,断开了连接,会自动重连。master 如果发现有多个 slave node 都来重新连接,仅仅会启动一个 rdb save 操作,用一份数据服务所有 slave node

主从复制的断点续传

从 redis2.8 开始,就支持主从复制的断点续传,如果主从复制过程中,网络连接断掉了,那么可以接着上次复制的地方,继续复制下来,而不是从头开始复制一份

master node 会在内存中存在一个 backlog,master 和 slave 都会保存一个 replica offset 还有一个 master id,offset就是保存在 backlog中的,如果 master 和 slave 网络连接断掉了,slave 会让 master 从上次的 replica offset 开始继续复制。但是如果没有找到对应的 offset,那么就会执行一次 resynchronization

无磁盘化复制

master 在内存中直接创建 rdb,然后发送给 slave,不会在自己本地落地磁盘了

# 是否开启无磁盘化配置,yes开启 no不开启,默认no
repl-diskless-sync no
# 等待一定时长再开始复制,因为要等更多 slave 重新连接过来,默认配置 5秒,单位是秒
repl-diskless-sync-delay 5

过期 key 处理

slave 不会过期,只会等待 master 过期 key。
如果 master 过期了一个 key,或者通过 LRU 淘汰了一个 key,那么会模拟一条 del 命令发送给 slave

redis replication(主从复制)的完整运行流程

复制的完整流程

  • slave node 启动,仅仅保存 master node 的信息,包括 master node 的 host 和 ip,但是复制流程没开始
    【注: master host 和 ip 是从哪儿来的?redis.conf 里面的 slaveof 配置的】
  • slave node 发送 ping 命令给 master node
  • 口令认证,如果 master 设置了 requirepass,那么 salve node 必须发送 masterauth 的口令过去进行认证
  • 口令认证,如果 master 设置了 requirepass,那么 salve node 必须发送 masterauth的口令过去进行认证
  • master node 第一次执行全量复制,将所有数据发给 slave node
  • master node 后续持续写命令,异步复制给 slave node

数据同步相关的核心机制

主要指的是第一次 slave 连接 master 的时候,执行的全量复制,那个过程里面的一些细节机制

  • master 和 slave 都会维护一个 offset
    master 会在自身不断累加 offset,slave 也会在自身不断累加 offset;slave 每秒都会上报自己的 offset 给 master,同时 master 也会保存每个 slave 的offset。这个倒不是说特定就用在全量复制的,主要是 master 和 slave 都要知道各自的数据的 offset,才能知道互相之间的数据不一致的情况
  • backlog
    master node 有一个 backlog,默认是 1MB 大小,master node 给 slave node 复制数据时,也会将数据在 backlog 中同步写一份;backlog 主要是用来做全量复制中断时的增量复制的
  • master run id
    info server可以看到 master run id
127.0.0.1:6379> info server
# Server
redis_version:3.2.8
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:ee73a8e0c4c779ea
redis_mode:standalone
os:Linux 3.10.0-957.el7.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
gcc_version:4.8.5
process_id:7842
run_id:0f142c4912fd93a030c02237fad7bde72a3d5b66
tcp_port:6379
uptime_in_seconds:21
uptime_in_days:0
hz:10
lru_clock:9753411
executable:/usr/local/bin/redis-server
config_file:/etc/redis/6379.conf

如果根据 host + ip 定位 master node,是不靠谱的,如果 master node 重启或者数据出现了变化,那么 slave node 应该根据不同的 run id 区分,run id 不同就做全量复制。如果需要不更改 run id 重启 redis,可以使用 redis-cli debug reload 命令

  • psync
    从节点使用 psync 从 master node 进行复制,paync runid offset。master node 会根据自身的情况返回响应信息,可能是 FULLRESYNC runid offset 触发全量复制,可能是 CONTINUE 触发增量复制

全量复制

① master 执行 bgsave,在本地生成一份 rdb快照文件
② master node 将 rdb 快照文件发送给 salve node,如果 rdb 复制时间超过 60秒(repl-timeout),那么 slave node 就会认为复制失败,可以适当调大这个参数
③ 对于千兆网卡的机器,一般每秒传输 100MB,6G 文件,还可能超过 60s
④ master node 在生成 rdb 时,会将所有新的写命令缓存在内存中,在 salve node 保存了 rdb 之后,再将新的写命令复制给 slave node
⑤ client-output-buffer-limit slave 256MB 64MB 60
如果在复制期间,内存缓存区持续消耗超过 64MB,或者一次性超过 256MB,那么停止复制,复制失败
⑥ slave node 接收到 rdb 之后,清空自己的旧数据,然后重新加载 rdb 到自己的内存中,同时基于旧的数据版本对外提供服务
⑦ 如果 slave node 开启了 AOF,那么会立即执行 BGREWRITEAOP,重写 AOF
【注:rdb 生成、rdb 通过网络拷贝、slave 旧数据的清理、slave aof rewrite,很耗费时间】

增量复制

① 如果全量复制过程中,master-slave 网络连接断掉,那么 slave 重新连接master时,会触发增量复制
② master 直接从自己的 backlog 中获取部分丢失的数据,发送给 slave node,默认 backlog 就是 1MB
③ master 就是根据 slave 发送的 psync 中的 offset 来从 backlog 中获取数据的

heartbeat

主从节点互相都会发送 heartbeat 信息。master 默认每隔 10 秒发送一次 heartbeat,slave node 每隔 1秒发送一个 heartbeat

异步复制

master 每次接收到写命令之后,先在内部写入数据,然后异步发送给 slave node

读写分离的配置

(以两台虚拟机为例)

准备两台虚拟机

# 主虚拟机 ip
192.168.1.132
# 从虚拟机 ip
192.168.1.133

配置主虚拟机的redis.conf

# 这里仅仅展示主要配置(以从未改动的配置为准)
# 因为是主节点,所以必须配置好 持久化机制

# 配置后台启动
daemonize  yes
# 以下配置为文件存放位置和端口号,可自行配置
# 设置redis的pid文件位置
pidfile  /var/run/redis_6379.pid
# 设置redis的监听端口号
port  6379
# 设置持久化文件存放为准
dir  /var/redis/6379

# 配置bind,这里必须配置自己的ip,不能配置 127.0.0.1也不能注释
bind 192.168.1.132

配置从虚拟机的redis.conf

# 这里仅仅展示主要配置(以从未改动的配置为准)
# 因为是主节点,所以必须配置好 持久化机制

# 配置后台启动
daemonize  yes
# 以下配置为文件存放位置和端口号,可自行配置
# 设置redis的pid文件位置
pidfile  /var/run/redis_6379.pid
# 设置redis的监听端口号
port  6379
# 设置持久化文件存放为准
dir  /var/redis/6379

# 配置bind,这里必须配置自己的ip,不能配置 127.0.0.1也不能注释
bind 192.168.1.133

# 配置主节点ip以及主节点 redis 的端口号
slaveof  192.168.1.132 6379

# 配置强制读写分离
# redis slave node只读,默认开启
# 开启了只读的redis slave node,会拒绝所有的写操作,这样可以强制搭建成读写分离的架构
slave-read-only yes

关闭防火墙,保证能 telnet 对方

systemctl status firewalld.service
systemctl stop firewalld.service
systemctl start firewalld.service

启动

启动先启动主节点的,再启动从节点的

主节点操作,仅供参考,以实际为准

# 先开启 redis,再客户端
redis-cli -h 192.168.1.132

192.168.1.132:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.1.133,port=6379,state=online,offset=1751,lag=0
master_repl_offset:1751
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:1750

######################################
# 可以对比参考
192.168.1.132:6379> keys *
1) "aaa"

192.168.1.132:6379> set bbb 222
OK
192.168.1.132:6379> get bbb
"222"

从节点操作,仅供参考,以实际为准

# 先开启 redis,再客户端
redis-cli -h 192.168.1.133
192.168.1.133:6379> info replication
# Replication
role:slave
master_host:192.168.1.132
master_port:6379
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_repl_offset:29
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

######################################
# 可以对比参考
192.168.1.133:6379> keys *
1) "aaa"

# 主节点写入,从节点也能读到
192.168.1.133:6379> get bbb
"222"

# 从节点只能读,不能写
192.168.1.133:6379> set ccc 123
(error) READONLY You can't write against a read only slave.

水平扩容redis读节点,提升度吞吐量

可以在其他服务器上搭建redis从节点,(从节点配置见上文),单个从节点读请QPS在5万左右,两个redis从节点,所有的读请求打到两台机器上去,承载整个集群读QPS在10万+

redis 压测(了解即可)

如果你要对自己刚刚搭建好的 redis 做一个基准的压测,测一下你的 redis 的性能和 QPS(query per second)
redis 自己提供的 redis-benchmark 压测工具,是最快捷最方便的

# 在 redis 的 src 目录下,输入如下命令
./redis-benchmark -h 192.168.1.132

# 可以配置参数
redis-benchmark [-h <host>] [-p <port>] [-c <clients>]

-h <hostname> 指定服务器主机名(默认 127.0.0.1)
-p <port> 指定服务器端口(默认 6379)
-s <socket> 指定服务器 socket
-a <password> Redis 认证密码
-c <clients> 指定并发连接数(默认50)
-n <requests> 指定请求数(默认100000)
-d <sise> 以字节的形式指定 SET/GET 值的数据大小(默认2)
--dbnum <db> 选择指定的数据库号(默认0)
-q 退出,仅显示 query/sec
......

实例:使用20个并行客户端,总共10万个请求

###########################
====== PING_INLINE ======
  100000 requests completed in 0.76 seconds
  20 parallel clients
  3 bytes payload
  keep alive: 1

100.00% <= 0 milliseconds
131926.12 requests per second

====== PING_BULK ======
  100000 requests completed in 0.73 seconds
  20 parallel clients
  3 bytes payload
  keep alive: 1

100.00% <= 0 milliseconds
136239.78 requests per second

====== SET ======
  100000 requests completed in 1.08 seconds
  20 parallel clients
  3 bytes payload
  keep alive: 1

99.94% <= 1 milliseconds
99.96% <= 4 milliseconds
99.98% <= 7 milliseconds
100.00% <= 7 milliseconds
93023.25 requests per second

====== GET ======
  100000 requests completed in 0.77 seconds
  20 parallel clients
  3 bytes payload
  keep alive: 1

100.00% <= 0 milliseconds
130208.34 requests per second
......

Redis 主从架构下如何才能做到 99.99% 的高可用性

  • 图解 redis 的不可用

什么是 99.99% 高可用性

用一句话概括,在 1 年内(365天),在 99.99% 的时间内,你的系统都是可以对外提供服务的,那就是高可用性

redis 的不可用是什么?不可用的后果?

redis 怎么才能做到高可用(redis 基于哨兵的高可用)

标签:node,slave,读写,分离,redis,6379,复制,master
来源: https://www.cnblogs.com/xiaoyangabc/p/16316033.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有