美文网首页
高并发redis - 读写分离支撑qps10w+

高并发redis - 读写分离支撑qps10w+

作者: coder爱唱歌 | 来源:发表于2020-03-29 01:45 被阅读0次

    之前讲到单机redis的为了保证数据安全,必须做好数据备份等基础工作。但是如果流量越来越大,
    redis的读写请求压力越来越大,到了一个极限值,性能依旧不够用我们应该如何处理?

    这边文章就分为以下几步来一次介绍redis读写分离:

    • 1、两个问题分析redis瓶颈
    • 2、解释什么是读写分离以及读写分离流程与原理
    • 3、读写分离对于数据的安全意义
    • 4、docker搭建一主两从读写分离的实战(附带配置和操作流程)
    • 5、总结

    1、两个问题分析redis瓶颈

    所以先看看一下两个问题:

    • 1.redis不能支撑高并发的瓶颈在哪里?
      • 第一,一台redis的性能首先和机器性能,业务复杂度,以及redis操作的复杂度这三点是密切相关的。
      • 如果是单纯的String ,key,value操作,性能一般能到1-5w qps。
      • 第二,当一台性能不够用,可以横向扩展机器,就能达到扩容的效果。
    单机redis瓶颈.png
    • 2.如何redis要支撑超过10w+的并发,那应该怎么做?
      • 单机redis几乎不可能超过10w+,除非机器性能非常好,物理机,维护好,操作简单
      • 所以必须能横向扩展,采取读写分离主从架构(master - slave)
        • 一个主节点,只写数据
        • 多个从节点,主节点把数据同步给多个从节点
        • 然后读就从从节点读,分摊读压力,从节点还可以横向扩展
    redis主从架构示意.png

    注意:读写分离是分摊读请求的压力,如果是写请求的操作瓶颈,需要通过cluster让多节点写,
    或者通过异步队列,异步完成写操作的方式解决

    2、解释什么是读写分离以及读写分离流程与原理

    读写分离就是基于redis replication搭建多个redis节点,然后分为master主节点,slave从节点。
    master节点主要作用是接收所有写请求,写数据,然后同步到slave。然后多个slave节点,每个都有
    全量的数据,分摊读请求。简单是说,就是master只负责写和同步数据到slave,slave只负责读。
    这种架构适用于读多写少的系统,slave可以横向扩展,接收更多的读请求。

    redis replication基本原理.png

    master和slave数据同步的完整流程

    首先介绍一下复制过程中的一些核心机制

    • offset

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

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

      • 主从节点互相都会发送heartbeat信息
      • master默认每隔10秒发送一次heartbeat,salve node每隔1秒发送一个heartbeat
    • 主从复制的断点续传

      • 如果主从复制过程中,网络连接断开了,那么可以接着上次复制的地方,连续复制下去,而不是从头开始复制一份
      • master node会在内存中存一个backlog,master和skave都会保存一个replica offset 还有一个master id ,offset就是保存在backlog中的,如果master和slave网络连接断掉了,slave会让master从上次的replica offset 开始继续复制。但是如果没有找到对应的offset,那么就会执行一次 resynchronhronization

    数据复制流程:

    • 复制的完整流程

      • msater就是根据slave发送的psync中的offset来从backlog中获取数据的
      • slave node内部有个定时任务,每秒检查是否有新的master node要连接和复制,如果发现,就跟master node建立socket网络连接。
      • slave node发送ping命令给master node
      • master node第一次执行全量复制,将所有数据发给slave node
      • master node后续持续将写命令,异步增量复制给slave node
      主从复制的完整的基本流程.png
    • 全量复制

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

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

      • master每次接收到写命令之后,先在内部写入数据,然后异步发送给slave node
    redis主从复制的原理.png

    3、读写分离对于数据的安全意义

    • 首先,master是必须做数据持久化的,因为这里是数据来源,slave做不做无所谓了。
    • 然后,没个slave都有全量数据,也就可以成为master的一个热备份,当master挂了,能顶上去
    • slave顶替master在后面哨兵继续讲。

    4、docker搭建一主两从读写分离的实战(附带配置和操作流程)

    都是放在/data/redis/redis.conf下,dir都是容器内的/data目录。
    redis的master节点配置:

    port 6379
    requirepass "123456"
    dbfilename "dump.rdb"
    dir "/data"
    logfile "/data/redis.log"
    save 10 5
    appendonly yes
    appendfsync everysec
    

    redis的slave配置(slave的ip和端口,填写自己的master,我这里是192.168.5.48 6379)

    port 6379
    requirepass "123456"
    slaveof 192.168.5.10 6379
    masterauth "123456"
    slave-read-only yes
    

    docker启动脚本

    docker run -d --name redis -p 6379:6379 -v /data/redis/:/data/ redis redis-server /data/redis.conf
    

    启动容器后,查看replication的命令

    docker exec -it redis /bin/bash
    redis-cli -h 127.0.0.1 -a 123456 -p 6379
    info replication 
    

    操作步骤

    • 准备三台centos虚拟机(可参照我之前的文章:virtualBox+vagrant搭建多节点虚机)
    • 复制master的redis配置到/data/redis/redis.conf
    • 使用docker启动命令启动master的redis
    • 另外两台虚拟机重复上面的操作,唯一不同的就是修改redis.conf内容为上面从节点的配置,注意修改slave of的ip和端口
    • 三个redis都启动完毕,就在每台机器上执行上面查看replication命令,查看集群是否搭建完毕。下图是搭建成功的示例。


      master设置成功replication信息.png
    slave设置成功replication信息.png

    验证数据同步:

    • 首先进入master的redis-cli ,执行 set name along
    • 然后去从节点去执行命令:get name ,如果发现,能获取到,就说明master把数据同步给了slave

    5、总结

    • 当面对读多写少的业务场景,可以选择redis主从复制,读写分离的架构
    • 单机是redis提高qps的瓶颈,好的架构能横向扩展
    • 主从复制,读写分离的一些缺点
      • 如何保证高可用?(这个后面在哨兵中讲解)
      • 每个redis都是全量数据,比较浪费内存(后面cluster有解决方案)

    相关文章

      网友评论

          本文标题:高并发redis - 读写分离支撑qps10w+

          本文链接:https://www.haomeiwen.com/subject/pytyuhtx.html