-----------------------------------------------------------------------------------------------------------------------html
三个重要的标准:java
---大型缓存架构中须要首先说一下:node
海量数据:支持海量数据缓存,支持大规模数据;mysql
高并发:在亿级QPS的场景下,能够作到知足业务需求;linux
高可用:表示redis能够作到而且尽量的作到能够持续使用。好比整年保持99.99%的时间处在可用状态,除非遇到各类断电等特殊灾害;nginx
-------------------------------------------------------------------------------------------------------web
商品详情页的系统架构介绍-->两种设计类型:redis
静态模板是固定的 数据库中的数据全量喧嚷到模板中,下次请求来了直接返回,速度也很快;算法
缺点:当数据上亿的时候,若是模板改定,把这些全部的数据在mysql中取出后渲染进模板,很是耗时,不现实;sql
设计缓存数据生产服务模块;
不须要再进行全量从新渲染,直接将最新的html模板推送到nginx服务器,请求过来后直接在nginx本地进行渲染进模板中返回请求;
-------------------------------------------------------------------------------------------------------
虚拟机中安装CentOS
启动一个virtual box虚拟机管理软件 使用CentOS 6.5镜像便可,CentOS-6.5-i386-minimal.iso
配置网络
vi /etc/sysconfig/network-scripts/ifcfg-eth0 ---- 修改linux的网络配置
删除对应的项目,保留以下的配置:
DEVICE=eth0
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=dhcp
wq保存;
重启网络:
service network restart
使用ifconfig查询当前自动分配的网址;
将当前的网址设置为静态ip,加入下面的静态配置:
BOOTPROTO=static
IPADDR=192.168.0.X
NETMASK=255.255.255.0
GATEWAY=192.168.0.1
网络服务重启:
service network restart
配置hosts【至关于给本机起别名】
vi /etc/hosts
192.168.0.X eshop-cache01
其余主机,添加相似配置。实现本机的hostname到ip地址的映射
配置SecureCRT【本人使用的Xshell 感受也很好用】
此时就可使用SecureCRT从本机链接到虚拟机进行操做了
关闭linux防火墙
service iptables stop
service ip6tables stop
chkconfig iptables off
chkconfig ip6tables off
vi /etc/selinux/config
SELINUX=disabled
关闭windows的防火墙
配置yum
yum clean all
yum makecache
yum install wget
------------------------------------------------------------------------------------------
在每一个CentOS中都安装Java和Perl
(WinSCP,就是在windows宿主机和linux虚拟机之间互相传递文件的一个工具。)
(1)安装JDK
一、将jdk-7u60-linux-i586.rpm经过WinSCP上传到虚拟机中
二、安装JDK:rpm -ivh jdk-7u65-linux-i586.rpm
三、配置jdk相关的环境变量
vi .bashrc
export JAVA_HOME=/usr/java/latest
export PATH=$PATH:$JAVA_HOME/bin
source .bashrc
四、测试jdk安装是否成功:java -version
(2)安装Perl
yum install -y gcc
wget http://www.cpan.org/src/5.0/perl-5.16.1.tar.gz
tar -xzf perl-5.16.1.tar.gz
cd perl-5.16.1
./Configure -des -Dprefix=/usr/local/perl
make && make test && make install
perl -v
为何要装perl?咱们整个大型电商网站的详情页系统,复杂。java+nginx+lua,须要perl。
perl,是一个基础的编程语言的安装,tomcat,跑java web应用
------------------------------------------------------------------------------------------
三、在4个虚拟机中安装CentOS集群
(1)按照上述步骤,再安装三台如出一辙环境的linux机器
(2)另外三台机器的hostname分别设置为eshop-cache02,eshop-cache03,eshop-cache04
(3)安装好以后,在每台机器的hosts文件里面,配置好全部的机器的ip地址到hostname的映射关系
好比说,在eshop-cache01的hosts里面
192.168.31.187 eshop-cache01
192.168.31.xxx eshop-cache02
192.168.31.xxx eshop-cache03
192.168.31.xxx eshop-cache04
------------------------------------------------------------------------------------------
四、配置4台CentOS为ssh免密码互相通讯【此时四台linux虚拟机能够经过ssh实现无密码输入通讯】
(1)首先在四台机器上配置对本机的ssh免密码登陆
ssh-keygen -t rsa
生成本机的公钥,过程当中不断敲回车便可,ssh-keygen命令默认会将公钥放在/root/.ssh目录下
cd /root/.ssh
cp id_rsa.pub authorized_keys
将公钥复制为authorized_keys文件,此时使用ssh链接本机就不须要输入密码了
(2)接着配置三台机器互相之间的ssh免密码登陆
使用ssh-copy-id -i hostname命令将本机的公钥拷贝到指定机器的authorized_keys文件中
一、安装单机版tcl + redis
1. wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz
2. tar -xzvf tcl8.6.1-src.tar.gz
3. cd /usr/local/tcl8.6.1/unix/
4. ./configure
5. make && make install
6. 使用redis-3.2.8.tar.gz(截止2017年4月的最新稳定版)
7. tar -zxvf redis-3.2.8.tar.gz
8. cd redis-3.2.8
9. make && make test && make install
------------------------------------------------------------------------
二、redis的生产环境启动方案
若是通常的学习课程,你就随便用redis-server启动一下redis,作一些实验,这样的话,没什么意义
1. 要把redis做为一个系统的daemon进程去运行的,每次系统启动,redis进程一块儿启动
(1)redis utils目录下,有个redis_init_script脚本
(2)将redis_init_script脚本拷贝到linux的/etc/init.d目录中(初始化目录),将redis_init_script重命名为redis_6379,6379是咱们但愿这个redis实例监听的端口号
(3)修改redis_6379脚本的第6行的REDISPORT,设置为相同的端口号(默认就是6379)
(4)建立两个目录:
/etc/redis(存放redis的配置文件),
/var/redis/6379(存放redis的持久化文件,也就是后面要使用的redis备份)
(5)修改redis配置文件(默认在根目录下,redis.conf),拷贝到/etc/redis目录中,修更名称为6379.conf
(6)修改redis.conf中的部分配置为生产环境
daemonize yes 让redis以daemon进程运行(守护线程,能够理解为java运行时的jvm线程,在后台进行service服务) pidfile /var/run/redis_6379.pid 设置redis的pid文件位置 【/var/run 目录下放的是各程序的pid】 port 6379 设置redis的监听端口号 dir /var/redis/6379 设置持久化文件的存储位置
(7)启动redis,执行cd /etc/init.d, chmod 777 redis_6379,
./redis_6379 start
(8)确认redis进程是否启动,ps -ef | grep redis
(9)让redis跟随系统启动自动启动
在redis_6379脚本中,最上面,加入两行注释
# chkconfig: 2345 90 10
# description: Redis is a persistent key-value database
在Xshell中执行 chkconfig redis_6379 on
------------------------------------------------------------------------
三、redis cli的使用
redis-cli SHUTDOWN,链接本机的6379端口中止redis进程;
redis-cli -h 127.0.0.1 -p 6379 SHUTDOWN,制定要链接的ip和端口号
redis-cli PING,ping redis的端口,看是否正常
redis-cli,进入交互式命令行:
存取删测试:
set k1 v1
get k1
del k1
------------------------------------------------------------------------------------------------
redis的技术,包括4块:
redis各类数据结构和命令的使用,包括java api的使用,这类操做命令其余的博客很是完善,能够常常性的查询熟悉;
redis一些特殊的解决方案的使用,pub/sub消息系统,分布式锁,输入的自动完成等;
redis平常的管理相关的命令;
redis企业级的集群部署和架构;
Note:
--- Redis在不使用备份的状况下会产生缓存雪崩问题,也就是redis宕机后,没有备份的状况下,全部查询操做所有直接涌入数据库,致使数据库机器宕机;
两种备份方式分析:
---下边堆 redis 写如数据的两种方式进行分析:
原理图:
redis 的 AOF 下的 rewrite 机制原理:
AOF和RDB两种模式:
AOF机制对每条写入命令做为日志,以append-only的模式写入一个日志文件中,在redis重启的时候,能够经过回放AOF日志中的写入指令来从新构建整个数据集
若是咱们想要redis仅仅做为纯内存的缓存来用,那么能够禁止RDB和AOF全部的持久化机制【可是采用这种方式的项目是个高危项目】
经过RDB或AOF,均可以将redis内存中的数据给持久化到磁盘上面来,而后能够将这些数据备份到别的地方去,好比云服务
若是redis挂了,服务器上的内存和磁盘上的数据都丢了,能够从云服务上拷贝回来以前的数据,放到指定的目录中,而后从新启动redis,redis就会自动根据持久化数据文件中的数据,去恢复内存中的数据,继续对外提供服务【这个地方就能够看出redis确实很高级】
若是同时使用RDB和AOF两种持久化机制,那么在redis重启的时候,会使用AOF来从新构建数据,由于AOF中的数据更加完整
RDB持久化机制,对redis中的数据执行周期性的持久化,也就是每一个固定的时间去作一次内存快照的保存工做,适合作冷备份。
-------------------------------------------------------------------------------------
RDB持久化机制的优势
(1)RDB会生成多个数据文件,每一个数据文件都表明了某一个时刻中redis的数据,这种多个数据文件的方式,很是适合作冷备,能够将这种完整的数据文件发送到一些远程的安全存储上去,好比说Amazon的S3云服务上去,在国内能够是阿里云的ODPS分布式存储上,以预约好的备份策略来按期备份redis中的数据
(2)RDB对redis对外提供的读写服务,影响很是小,可让redis保持高性能,由于redis主进程只须要fork一个子进程,让子进程执行磁盘IO操做来进行RDB持久化便可
(3)相对于AOF持久化机制来讲,直接基于RDB数据文件【AOF为指令日志】来重启和恢复redis进程,更加快速。【rdb基于数据,恢复速度快】
-------------------------------------------------------------------------------------
RDB持久化机制的缺点
(1)若是想要在redis故障时,尽量少的丢失数据,那么RDB没有AOF好。
通常来讲,RDB数据快照文件,都是每隔5分钟,或者更长时间生成一次,这个时候就得接受一旦redis进程宕机,那么会丢失最近5分钟的数据。
(2)RDB每次在fork子进程来执行RDB快照数据文件生成的时候,若是数据文件特别大,可能会致使对客户端提供的服务暂停数毫秒,或者甚至数秒
-------------------------------------------------------------------------------------
AOF持久化机制的优势
(1)AOF能够更好的保护数据不丢失,通常AOF会每隔1秒,经过一个后台线程执行一次fsync操做,最多丢失1秒钟的数据。
(2)AOF日志文件以append-only模式写入,因此没有任何磁盘寻址的开销,写入性能很是高,并且文件不容易破损,即便文件尾部破损,也很容易修复
(3)AOF日志文件即便过大的时候,出现后台重写操做,也不会影响客户端的读写。由于在rewrite log的时候,会对其中的指导进行压缩,建立出一份须要恢复数据的最小日志出来。在建立新日志文件的时候,老的日志文件仍是照常写入。当新的merge后的日志文件ready的时候,再交换新老日志文件便可。
(4)AOF日志文件的命令经过很是可读的方式进行记录,这个特性很是适合作灾难性的误删除的紧急恢复。好比某人不当心用 【 flushall 】 命令清空了全部数据,只要这个时候后台rewrite尚未发生,那么就能够当即拷贝AOF文件,将最后一条flushall命令给删了,而后再将该AOF文件放回去,就能够经过恢复机制,自动恢复全部数据。
-------------------------------------------------------------------------------------
AOF持久化机制的缺点
(1)对于同一份数据来讲,AOF日志文件一般比RDB数据快照文件更大
(2)AOF开启后,支持的写QPS会比RDB支持的写QPS低,由于AOF通常会配置成每秒fsync一第二天志文件,固然,每秒一次fsync,性能也仍是很高的
(3)之前AOF发生过bug,就是经过AOF记录的日志,进行数据恢复的时候,没有恢复如出一辙的数据出来。因此说,相似AOF这种较为复杂的基于命令日志/merge/回放的方式,比基于RDB每次持久化一份完整的数据快照文件的方式,更加脆弱一些,容易有bug。不过AOF就是为了不rewrite过程致使的bug,所以每次rewrite并非基于旧的指令日志进行merge的,而是基于当时内存中的数据进行指令的从新构建,这样健壮性会好不少。
-------------------------------------------------------------------------------------
linux环境下 redis 的默认配置中 AOF 模式是关闭的 能够从配置文件 appendonly=no 看到,而 默认打开的是 RDB 模式;
在两种模式都开启的状况下,作数据恢复的时候优先使用AOF的数据;
下面重点对AOF模式的配置进行分析:
设置appendonly=yes;
设置appendfsync,对于设置linux缓存oscache支持的选项 always, everysec,no;
设置auto-aof-rewrite-percentage 1-100 用来设置如今aof文件大小相比于上次rewrite时空间增长的比例 好比设置为100 则表示 在比上一次增大了一倍时再次rewrite
设置auto-aof-rewrite-min-size XXmb 最小rewrite空间大小,以mb为单位,必须超过该空间才有可能触发rewrite,每次都会进行比较;
rewrite的实现图,在建立新aof文件时若是有新的client加入数据时的场景,新的数据会都保存在新旧aof文件中后再删除旧的aof文件;
RDB很是适合作冷备,每次生成以后,就不会再有修改了。
一、数据备份方案
(1)写linux的定时任务调度脚本,使用crontab定时调度脚本去作数据备份
(2)每小时都copy一份rdb的备份,到一个目录中去,仅仅保留最近48小时的备份
(3)天天都保留一份当日的rdb的备份,到一个目录中去,仅仅保留最近1个月的备份【至关于每月保存30份备份】
(4)每次copy备份的时候,都把太旧的备份给删了
(5)天天晚上将当前服务器上全部的数据备份,发送一份到远程的云服务上去【云服务上觉得单位】
二、数据恢复方案
(1)若是是redis进程挂掉,那么重启redis进程便可,直接基于AOF日志文件恢复数据
(2)若是是redis进程所在机器挂掉,那么重启机器后,尝试重启redis进程,尝试直接基于AOF日志文件进行数据恢复,AOF没有破损,也是能够直接基于AOF恢复的,AOF append-only,顺序写入,若是AOF文件破损,那么用 redis-check-aof fix【损坏部分容忍丢失,其实只丢失了一秒的数据量】
(3)若是redis当前最新的AOF和RDB文件出现了丢失/损坏,那么能够尝试基于该机器上当前的某个最新的RDB数据副本进行数据恢复
当前最新的AOF和RDB文件都出现了丢失/损坏到没法恢复,通常不是机器的故障,人为
/var/redis/6379下的文件给删除了,找到RDB最新的一份备份,小时级的备份能够了,小时级的确定是最新的,copy到redis里面去,就能够恢复到某一个小时的数据
容灾演练
中止redis,关闭aof,拷贝rdb备份,重启redis,确认数据恢复,直接在命令行热修改redis配置,打开aof,这个redis就会将内存中的数据对应的日志,写入aof文件中,此时aof和rdb两份数据文件的数据就同步了。
redis config set
热修改配置参数,可能配置文件中的实际的参数没有被持久化的修改,再次中止redis,手动修改配置文件,打开aof的命令,再次重启redis。
(4)若是当前机器上的全部RDB文件所有损坏,那么从远程的云服务上拉取最新的RDB快照回来恢复数据。
(5)若是是发现有重大的数据错误,好比某个小时上线的程序一会儿将数据所有污染了,数据全错了,那么能够选择某个更早的时间点,对数据进行恢复
单机的redis的通常场景下的极限值差很少读的QPS在5万左右,固然也收服务器的性能配置影响,因此高于这个极限值很大的境况下,redis随时有崩掉的危险,那么
怎么作到更高的QPS呢,总的思路就是读写分离,同时增长读的redis个数,由于在一般的场景下,读远远大于写;
这就引出了redis的主从结构话设计;
主从结构框架配置 必须实现 master 的持久化!!!
主从reids间的同步原理:
runid的做用:
一、复制的完整流程
(1)slave node启动,仅仅保存master node的信息,包括master node的host和ip,可是复制流程没开始
master host和ip是从哪儿来的,redis.conf里面的slaveof配置的
(2)slave node内部有个定时任务,每秒检查是否有新的master node要链接和复制,若是发现,就跟master node创建socket网络链接
(3)slave node发送ping命令给master node
(4)口令认证,若是master设置了requirepass,那么salve node必须发送masterauth的口令过去进行认证
(5)master node第一次执行全量复制,将全部数据发给slave node
(6)master node后续持续将写命令,异步复制给slave node
二、数据同步相关的核心机制
指的就是第一次slave链接msater的时候,执行的全量复制,那个过程里面你的一些细节的机制
(1)master和slave都会维护一个offset
master会在自身不断累加offset,slave也会在自身不断累加offset
slave每秒都会上报本身的offset给master,同时master也会保存每一个slave的offset
这个倒不是说特定就用在全量复制的,主要是master和slave都要知道各自的数据的offset,才能知道互相之间的数据不一致的状况
(2)backlog
master node有一个backlog,默认是1MB大小
master node给slave node复制数据时,也会将数据在backlog中同步写一份
backlog主要是用来作全量复制中断候的增量复制的
(3)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命令
(4)psync
从节点使用psync从master node进行复制,psync runid offset
master node会根据自身的状况返回响应信息,多是FULLRESYNC runid offset触发全量复制,多是CONTINUE触发增量复制
三、全量复制
(1)master执行bgsave,在本地生成一份rdb快照文件
(2)master node将rdb快照文件发送给salve node,若是rdb复制时间超过60秒(repl-timeout),那么slave node就会认为复制失败,能够适当调节大这个参数
(3)对于千兆网卡的机器,通常每秒传输100MB,6G文件,极可能超过60s
(4)master node在生成rdb时,会将全部新的写命令缓存在内存中,在salve node保存了rdb以后,再将新的写命令复制给salve node
(5)client-output-buffer-limit slave 256MB 64MB 60,若是在复制期间,内存缓冲区持续消耗超过64MB,或者一次性超过256MB,那么中止复制,复制失败
(6)slave node接收到rdb以后,清空本身的旧数据,而后从新加载rdb到本身的内存中,同时基于旧的数据版本对外提供服务
(7)若是slave node开启了AOF,那么会当即执行BGREWRITEAOF,重写AOF
rdb生成、rdb经过网络拷贝、slave旧数据的清理、slave aof rewrite,很耗费时间
若是复制的数据量在4G~6G之间,那么极可能全量复制时间消耗到1分半到2分钟
四、增量复制
(1)若是全量复制过程当中,master-slave网络链接断掉,那么salve从新链接master时,会触发增量复制
(2)master直接从本身的backlog中获取部分丢失的数据,发送给slave node,默认backlog就是1MB
(3)msater就是根据slave发送的psync中的offset来从backlog中获取数据的
五、heartbeat
主从节点互相都会发送heartbeat信息
master默认每隔10秒发送一次heartbeat,salve node每隔1秒发送一个heartbeat
六、异步复制
master每次接收到写命令以后,如今内部写入数据,而后异步发送给slave node
一、在slave node上配置以下便可:
slaveof 192.168.X.X 6379
二、强制读写分离
基于主从复制架构,实现读写分离 redis slave node必须设置为只读模式,默认开启,
slave-read-only yes
开启了只读的redis slave node,会拒绝全部的写操做,这样能够强制搭建成读写分离的架构
三、集群安全认证
master上启用安全认证,requirepass passwd
slave上设置链接口令,masterauth passwd
两个passwd须要保持一致
四、bind 对应的 IP
在master 和 slave 上都设置bind IP,默认为127.0.0.1 这里须要设置本身的虚拟机的ip
----------------------------------------------
五、进行验证
先开启master,使用
redis-cli -h IP -a passwd
命令操做,本人操做过,若是不加 -a passwd参数会出现 (error) NOAUTH Authentication required.错误,输入后进入redis命令号 输入
info replication
------------------------------------------------
进行验证
验证结果
【从中也能够看到 master和slave的offset此时是不一致的】
六、而后开启slave从redis; 输入
redis-cli -h IP
而后输入
info replication
进行信息验证;
验证结果
主从数据验证:
master:
slave:
能够看到master的RDB数据已经传到了slave中; 同时咱们也能够知道,若是在slave上试图添加数据,会被无情的拒绝;
----------------------------------------------------- 更新至2018.8.19 22.46 -----------------------------------------------------
进入 redis 安装目录的 src目录下;
执行
redis-benchmark -h IP -c n1 -n n2 -d n3
进行测试
-c <clients> Number of parallel connections (default 50) -n <requests> Total number of requests (default 100000) -d <size> Data size of SET/GET value in bytes (default 2)
本人机器测试以下:
咱们能够看到 在Get操做中 QPS 为 76863 至关于每秒1.7W的访问量,虚拟机的配置为1G内存单CPU,若是进行水平扩容2台,架构由一台master加三台slave,则支持7.6W*2 = 22W的QPS,固然在生产场景下,与访问的数据大小存在关系;
------------------------------------------------------------------------------------------
----主备切换
在主从架构中slave发生问题时,若是是一台slave出现问题,不会影响整个架构的运行,由于其余的slave会顶替该宕机的slave,可是若是master出现了宕机,就没有机器继续给
slave机器复制数据,因此这时候须要采用一种机制来实现高可用性;
如何实现缓存架构的高可用性
-----【增长哨兵 Sentinel Node】
------------------------------------------------------------------------------------------
经典的三点哨兵集群介绍:
-----【为何最少是3个哨兵,由于只要quorum 和 majority 都知足的状况下才能够进行故障转移】
若是哨兵集群中一个哨兵认为主节点宕机了,这种状况为sdowm,也就是主观宕机,此时可能存在误判,因此须要设置quorum,好比有三台机器,quorum设置
为2,则在有两台机器认为是sdown的状况下,变为odowm,也就是客观宕机,此时的判断通常是准确的。
哨兵是redis集群架构中很是重要的一个组件,主要功能以下:
(1)集群监控,负责监控redis master和slave进程是否正常工做
(2)消息通知,若是某个redis实例有故障,那么哨兵负责发送消息做为报警通知给管理员
(3)故障转移,若是master node挂掉了,会自动转移到slave node上
(4)配置中心,若是故障转移发生了,通知client客户端新的master地址
哨兵自己也是分布式的,做为一个哨兵集群去运行,互相协同工做
(1)故障转移时,判断一个master node是宕机了,须要大部分的哨兵都赞成才行,涉及到了分布式选举的问题
(2)即便部分哨兵节点挂掉了,哨兵集群仍是能正常工做的,由于若是一个做为高可用机制重要组成部分的故障转移系统自己是单点的,那就很坑爹了
哨兵的核心知识 ----- 哨兵+redis部署架构
(1)哨兵至少须要3个实例,来保证本身的健壮性
(2)哨兵 + redis主从的部署架构,是不会保证数据零丢失的,只能保证redis集群的高可用性
(3)对于哨兵 + redis主从这种复杂的部署架构,尽可能在测试环境和生产环境,都进行充足的测试和演练
------------------------------------------------------------------------------------------
首先说一下这里有个坑爹的地方就是 坑了我三天才得以解决,就是哨兵在监视master 和 slave的时候,都须要配置密码,sentinel auth-pass mymaster redis-pass 这一步我配置的过程当中漏掉了,致使哨兵一直监视不了主从架构,因此在配置的过程当中必定要加上;
基本配置:
哨兵默认用26379端口,默认不能跟其余机器在指定端口连通,只能在本地访问 mkdir /etc/sentinal mkdir -p /var/sentinal/5000 /etc/sentinal/5000.conf
在5000.conf文件中进行配置: port 5000 bind 192.168.1.108 dir /var/sentinal/5000 sentinel monitor mymaster 192.168.1.108 6379 2 sentinel down-after-milliseconds mymaster 30000 //超过多少毫秒跟一个redis实例断了链接,哨兵就可能认为这个redis实例挂了 sentinel failover-timeout mymaster 60000 //执行故障转移的timeout超时时长 sentinel parallel-syncs mymaster 1 //选举出新的master后 一次性把几个slave挂载上去
sentinel auth-pass mymaster redis-pass
port 5000 bind 192.168.1.109 dir /var/sentinal/5000 sentinel monitor mymaster 192.168.1.108 6379 2 sentinel down-after-milliseconds mymaster 30000 sentinel failover-timeout mymaster 60000 sentinel parallel-syncs mymaster 1
sentinel auth-pass mymaster redis-pass
port 5000 bind 192.168.1.105 dir /var/sentinal/5000 sentinel monitor mymaster 192.168.1.108 6379 2 sentinel down-after-milliseconds mymaster 30000 sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
sentinel auth-pass mymaster redis-pass
3、启动哨兵进程 在eshop-cache0一、eshop-cache0二、eshop-cache03三台机器上,分别启动三个哨兵进程,组成一个集群,观察一下日志的输出
redis-sentinel /etc/sentinal/5000.conf
redis-server /etc/sentinal/5000.conf --sentinel
日志里会显示出来,每一个哨兵都能去监控到对应的redis master,并可以自动发现对应的slave,哨兵之间互相会自动进行发现,用的就是以前说的pub/sub,消息发布和订阅channel消息系统和机制
4、检查哨兵状态 redis-cli -h 192.168.1.108 -p 5000
sentinel master mymaster
SENTINEL slaves mymaster
SENTINEL sentinels mymaster
SENTINEL get-master-addr-by-name mymaster
配置成功后的运行截图:
master的哨兵信息:
Slave上的哨兵信息:
master的哨兵监视信息:
slave的监视信息:
模式master 宕机后的情景:
将master的端口关闭掉,或者直接关闭master虚拟机,
第一种状况:在client不断往master写入数据,在准备将数据异步拷贝给各个slave的时候,此时master宕机的状况下,哨兵会选举新的master,而后clinet就会向
新的master写入数据,此时原来的master里边原来写入的那块数据就丢失了;
第二种状况脑裂:
也就是master因为异常缘由,独立出slave所在的网络,可是master能够继续工做,但此时哨兵检测到master的异常后,从新选出一个slave做为新的master,
此时的场景下存在了两个master,在新的master选举出来以前,而后client继续向原来的master写入数据,当选举新master完成后,原来的master恢复被被设置
为slave,此时旧的master缓存的数据就会被覆盖,致使数据丢失;
------------------------------------------------------------------
一、两种数据丢失的状况
主备切换的过程,可能会致使数据丢失
(1)异步复制致使的数据丢失
由于master -> slave的复制是异步的,因此可能有部分数据还没复制到slave,master就宕机了,此时这些部分数据就丢失了
(2)脑裂致使的数据丢失
脑裂,也就是说,某个master所在机器忽然脱离了正常的网络,跟其余slave机器不能链接,可是实际上master还运行着
此时哨兵可能就会认为master宕机了,而后开启选举,将其余slave切换成了master
这个时候,集群里就会有两个master,也就是所谓的脑裂
此时虽然某个slave被切换成了master,可是可能client还没来得及切换到新的master,还继续写向旧master的数据可能也丢失了
所以旧master再次恢复的时候,会被做为一个slave挂到新的master上去,本身的数据会清空,从新重新的master复制数据
------------------------------------------------------------------
解决方案:
在redis的配置文件配置参数:
min-slaves-to-write 1
min-slaves-max-lag 10
要求至少有1个slave,数据复制和同步的延迟不能超过10秒,若是说一旦全部的slave,数据复制和同步的延迟都超过了10秒钟,那么这个时候,master就不会再接收任何请求了.
要求至少有1个slave,数据复制和同步的延迟不能超过10秒
若是说一旦全部的slave,数据复制和同步的延迟都超过了10秒钟,那么这个时候,master就不会再接收任何请求了
上面两个配置能够减小异步复制和脑裂致使的数据丢失
(1)减小异步复制的数据丢失
有了min-slaves-max-lag这个配置,就能够确保说,一旦slave复制数据和ack延时太长,就认为可能master宕机后损失的数据太多了,那么就拒绝写请求[可能redis会处理暂时写入,保存到本身一个缓存区,详见上边的“处理图”],这样能够把master宕机时因为部分数据未同步到slave致使的数据丢失下降的可控范围内
(2)减小脑裂的数据丢失
若是一个master出现了脑裂,跟其余slave丢了链接,那么上面两个配置能够确保说,若是不能继续给指定数量的slave发送数据,并且slave超过10秒没有给本身ack消息,那么就直接拒绝客户端的写请求
这样脑裂后的旧master就不会接受client的新数据,也就避免了数据丢失
上面的配置就确保了,若是跟任何一个slave丢了链接,在10秒后发现没有slave给本身ack,那么就拒绝新的写请求
所以在脑裂场景下,最多就丢失10秒的数据
------------------------------------------------------------------------------------------
如何在保持读写分离+高可用的架构下,还能横向扩容支撑1T+海量数据
一、redis cluster vs. replication + sentinal
replication + sentinal:若是你的数据量不多,主要是承载高并发高性能的场景,好比你的缓存通常就几个G,单机足够了一个mater,多个slave,要几个slave跟你的要求的读吞吐量有关系,
而后本身搭建一个sentinal集群,去保证redis主从架构的高可用性,就能够了。
redis cluster:主要是针对海量数据+高并发+高可用的场景,海量数据,若是你的数据量很大,那么建议就用redis cluster
二、单机redis在海量数据面前的瓶颈
三、怎么才可以突破单机瓶颈,让redis支撑海量数据?
四、redis的集群架构
redis cluster
支撑N个redis master node,每一个master node均可以挂载多个slave node
读写分离的架构,对于每一个master来讲,写就写到master,而后读就从mater对应的slave去读
高可用,由于每一个master都有salve节点,那么若是mater挂掉,redis cluster这套机制,就会自动将某个slave切换成master
redis cluster(多master + 读写分离 + 高可用)
咱们只要基于redis cluster去搭建redis集群便可,不须要手工去搭建replication复制+主从架构+读写分离+哨兵集群+高可用
------针对海量数据+高并发+高可用的场景
讲解分布式数据存储的核心算法,数据分布的算法:
hash算法 -> 一致性hash算法(memcached) -> redis cluster,hash slot算法
用不一样的算法,就决定了在多个master节点的时候,数据如何分布到这些节点上去,解决这个问题。
简单的取模 hash函数实现:
【严重的弊端,对机器的个数进行取模】
一致性hash算法:
对于一致性hash算法热点问题的改进:
之前写的内容是master机器和slave机器分离,分别负责读写,可是到了 redis cluster以后,就再也不读写分离,全部的读和写都是经过master进行的;
针对key进行hash slot运算找slot;
关于redis cluster再也不使用三点哨兵集群模式那种读写分离的架构,全部的读和写都经过master就能够,若是想提升读或者写的QPS,则咱们只须要进行水平扩容,增长master就能够,其中
多台slave的做用是为了增长高可用,用来作主备切换使用;
理论补充部分:
---- 记得须要补充;------ 2019-3-31补充以下:
**********************
一、redis cluster 搭建部署:
中止以前全部的实例,包括redis主从和哨兵集群,使用 redis cluster。
redis cluster: 自动,master+slave复制和读写分离,master+slave高可用和主备切换,支持多个master的hash slot支持数据分布式存储。 1、redis cluster的重要配置 cluster-enabled <yes/no> cluster-config-file <filename>:
这是指定一个文件,供cluster模式下的redis实例将集群状态保存在那里,包括集群中其余机器的信息,好比节点的上线和下限,故障转移,不是咱们去维护的,给它指定一个文件,让redis本身去维护的 cluster-node-timeout <milliseconds>:
节点存活超时时长,超过必定时长,认为节点宕机,master宕机的话就会触发主备切换,slave宕机就不会提供服务 2、在三台机器上启动6个redis实例 --- 以其中一台举例 --- (1)在eshop-cache01上部署目录 /etc/redis/XXX (存放redis的配置文件)
/var/redis/XXX (存放redis的持久化文件) (2)编写配置文件 redis cluster集群,要求至少3个master,去组成一个高可用,健壮的分布式的集群,每一个master都建议至少给一个slave,3个master,3个slave,最少的要求,正式环境下,建议都是说在6台机器上去搭建,至少3台机器。 保证,每一个master都跟本身的slave不在同一台机器上,若是是6台天然更好,一个master+一个slave就死了 3台机器去搭建6个redis实例的redis cluster:
拿一台举例 ------------------------------------------------------- mkdir -p /etc/redis-cluster mkdir -p /var/log/redis mkdir -p /var/redis/7001 port 7001 cluster-enabled yes cluster-config-file /etc/redis-cluster/node-7001.conf cluster-node-timeout 15000 daemonize yes pidfile /var/run/redis_7001.pid dir /var/redis/7001 logfile /var/log/redis/7001.log bind 192.168.31.187 appendonly yes -------------------------------------------------------
至少要用3个master节点启动,每一个master加一个slave节点,先选择6个节点,启动6个实例,将上面的配置文件,在/etc/redis下放6个,分别为:
eshop-cache01:
7001.conf,7002.conf,
eshop-cache02:
7003.conf,7004.conf,
eshop-cache03:
7005.conf,7006.conf (3)准备生产环境的启动脚本 在/etc/init.d下,放6个启动脚本,分别为: redis_7001, redis_7002, redis_7003, redis_7004, redis_7005, redis_7006 每一个启动脚本内,都修改对应的端口号,以下图:

(4)分别在3台机器上,启动6个redis实例 将每一个配置文件中的slaveof给删除 3、建立集群 下面方框内的内容废弃掉 ======================================================================= wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz
tar -zxvf ruby-2.3.1.tar.gz ./configure -prefix=/usr/local/ruby make && make install cd /usr/local/ruby cp bin/ruby /usr/local/bin cp bin/gem /usr/local/bin wget http://rubygems.org/downloads/redis-3.3.0.gem
gem install -l ./redis-3.3.0.gem gem list --check redis gem ======================================================================= 由于,之前好比公司里面搭建集群,公司里的机器的环境,运维会帮你作好不少事情 在讲课的话,咱们手工用从零开始装的linux虚拟机去搭建,那确定会碰到各类各样的问题 yum install -y ruby yum install -y rubygems gem install redis cp /usr/local/redis-3.2.8/src/redis-trib.rb /usr/local/bin redis-trib.rb create --replicas 1 192.168.31.187:7001 192.168.31.187:7002 192.168.31.19:7003 192.168.31.19:7004 192.168.31.227:7005 192.168.31.227:7006
--replicas: 每一个master有几个slave 6台机器,3个master,3个slave,尽可能本身让master和slave不在一台机器上 yes redis-trib.rb check 192.168.31.187:7001
4、读写分离+高可用+多master 读写分离:每一个master都有一个slave 高可用:master宕机,slave自动被切换过去 多master:横向扩容支持更大数据量
二、redis cluster的实验,多master写入,主从复制,高可用
redis cluster搭建起来了
redis cluster,提供了多个master,数据能够分布式存储在多个master上; 每一个master都带着slave,自动就作读写分离; 每一个master若是故障,那么久会自动将slave切换成master,高可用
redis cluster的基本功能,来测试一下
一、实验多master写入 -> 海量数据的分布式存储
你在redis cluster写入数据的时候,实际上是你能够将请求发送到任意一个master上去执行
可是,每一个master都会计算这个key对应的CRC16值,而后对16384个hashslot取模,找到key对应的hashslot,找到hashslot对应的master
若是对应的master就在本身本地的话,set mykey1 v1,mykey1这个key对应的hashslot就在本身本地,那么本身就处理掉了
可是若是计算出来的hashslot在其余master上,那么就会给客户端返回一个moved error,告诉你,你获得哪一个master上去执行这条写入的命令
什么叫作多master的写入,就是每条数据只能存在于一个master上,不一样的master负责存储不一样的数据,分布式的数据存储
100w条数据,5个master,每一个master就负责存储20w条数据,分布式数据存储
大型的java系统架构,还专一在大数据系统架构,分布式,分布式存储,hadoop hdfs,分布式资源调度,hadoop yarn,分布式计算,hadoop mapreduce/hive
分布式的nosql数据库,hbase,分布式的协调,zookeeper,分布式通用计算引擎,spark,分布式的实时计算引擎,storm
若是你要处理海量数据,就涉及到了一个名词,叫作大数据,只要涉及到大数据,那么其实就会涉及到分布式
redis cluster,分布式
由于我来说java系统的架构,有时候跟其余人不同,纯搞java,可是我由于工做时间很长,早期专一作java架构,好多年,大数据兴起,就一直专一大数据系统架构
大数据相关的系统,也涉及不少的java系统架构,高并发、高可用、高性能、可扩展、分布式系统
会给你们稍微拓展一下知识面,从不一样的角度去讲解一块知识
redis,高并发、高性能、每日上亿流量的大型电商网站的商品详情页系统的缓存架构,来说解的,redis是做为大规模缓存架构中的底层的核心存储的支持
高并发、高性能、每日上亿流量,redis持久化 -> 灾难的时候,作数据恢复,复制 -> 读写分离,扩容slave,支撑更高的读吞吐,redis怎么支撑读QPS超过10万,几十万; 哨兵,在redis主从,一主多从,怎么保证99.99%可用性; redis cluster,海量数据
java架构课,架构思路和设计是很重要的,可是另一点,我但愿可以带着你们用真正java架构师的角度去看待一些技术,而不是仅仅停留在技术的一些细节的点
给你们从一些大数据的角度,去分析一下咱们java架构领域中的一些技术
天下武功,都出自一脉,研究过各类大数据的系统,redis cluster讲解了不少原理,跟elasticsearch,不少底层的分布式原理,都是相似的
redis AOF,fsync
elasticsearch创建索引的时候,先写内存缓存,每秒钟把数据刷入os cache,接下来再每隔必定时间fsync到磁盘上去
redis cluster,写能够到任意master,任意master计算key的hashslot之后,告诉client,重定向,路由到其余mater去执行,分布式存储的一个经典的作法
elasticsearch,创建索引的时候,也会根据doc id/routing value,作路由,路由到某个其余节点,重定向到其余节点去执行
分布式的一些,hadoop,spark,storm里面不少核心的思想都是相似的
后面,立刻把redis架构给讲完以后,就开始讲解业务系统的开发,包括高并发的商品详情页系统的大型的缓存架构,jedis cluster相关api去封装和测试对redis cluster的访问
jedis cluster api,就能够自动针对多个master进行写入和读取
二、实验不一样master各自的slave读取 -> 读写分离
在这个redis cluster中,若是你要在slave读取数据,那么须要带上readonly指令,get mykey1
redis-cli -c -h xxxx -p xxxxx
启动,就会自动进行各类底层的重定向的操做
实验redis cluster的读写分离的时候,会发现有必定的限制性,默认状况下,redis cluster的核心的理念,主要是用slave作高可用的,每一个master挂一两个slave,主要是作数据的热备,还有master故障时的主备切换,实现高可用的
redis cluster默认是不支持slave节点读或者写的,跟咱们手动基于replication搭建的主从架构不同的
slave node,readonly,get,这个时候才能在slave node进行读取
redis cluster,主从架构是出来,读写分离,复杂了点,也能够作,jedis客户端,对redis cluster的读写分离支持不太好的
默认的话就是读和写都到master上去执行的
若是你要让最流行的jedis作redis cluster的读写分离的访问,那可能还得本身修改一点jedis的源码,成本比较高
要否则你就是本身基于jedis,封装一下,本身作一个redis cluster的读写分离的访问api
核心的思路,就是说,redis cluster的时候,就没有所谓的读写分离的概念了
读写分离,是为了什么,主要是由于要创建一主多从的架构,才能横向任意扩展slave node去支撑更大的读吞吐量
redis cluster的架构下,实际上自己master就是能够任意扩展的,你若是要支撑更大的读吞吐量,或者写吞吐量,或者数据量,均可以直接对master进行横向扩展就能够了
也能够实现支撑更高的读吞吐的效果
不会去跟你们直接讲解的,不少东西都要带着一些疑问,未知,实际通过一些实验和操做以后,让你体会的更加深入一些
redis cluster,主从架构,读写分离,没说错,没有撒谎
redis cluster,不太好,server层面,jedis client层面,对master作扩容,因此说扩容master,跟以前扩容slave,效果是同样的
三、实验自动故障切换 -> 高可用性
redis-trib.rb check 192.168.31.187:7001
好比把master1,187:7001,杀掉,看看它对应的19:7004能不能自动切换成master,能够自动切换
切换成master后的19:7004,能够直接读取数据
再试着把187:7001给从新启动,恢复过来,自动做为slave挂载到了19:7004上面去
三、实现redis cluster的水平扩容
redis cluster模式下,不建议作物理的读写分离了
咱们建议经过master的水平扩容,来横向扩展读写吞吐量,还有支撑更多的海量数据
redis单机,读吞吐是5w/s,写吞吐2w/s
扩展redis更多master,那么若是有5台master,不就读吞吐能够达到总量25/s QPS,写能够达到10w/s QPS
redis单机,内存,6G,8G,fork类操做的时候很耗时,会致使请求延时的问题
扩容到5台master,能支撑的总的缓存数据量就是30G,40G
100台,600G,800G,甚至1T+,海量数据
----------------------------------------------------------
redis是怎么扩容的
------- 加入master 加入slave
一、加入新master
mkdir -p /var/redis/7007
port 7007
cluster-enabled yes
cluster-config-file /etc/redis-cluster/node-7007.conf
cluster-node-timeout 15000
daemonize yes
pidfile /var/run/redis_7007.pid
dir /var/redis/7007
logfile /var/log/redis/7007.log
bind 192.168.31.227
appendonly yes
搞一个7007.conf,再搞一个redis_7007启动脚本
手动启动一个新的redis实例,在7007端口上
redis-trib.rb add-node 192.168.31.227:7007 192.168.31.187:7001
redis-trib.rb check 192.168.31.187:7001
链接到新的redis实例上,cluster nodes,确认本身是否加入了集群,做为了一个新的master,
二、reshard一些数据过去
resharding的意思就是把一部分hash slot从一些node上迁移到另一些node上
redis-trib.rb reshard 192.168.31.187:7001
要把以前3个master上,总共4096个hashslot迁移到新的第四个master上去
How many slots do you want to move (from 1 to 16384)? 4096
检查一下分配的状况:
三、添加node做为slave
eshop-cache03
mkdir -p /var/redis/7008
port 7008
cluster-enabled yes
cluster-config-file /etc/redis-cluster/node-7008.conf
cluster-node-timeout 15000
daemonize yes
pidfile /var/run/redis_7008.pid
dir /var/redis/7008
logfile /var/log/redis/7008.log
bind 192.168.31.227
appendonly yes
redis-trib.rb add-node --slave --master-id 28927912ea0d59f6b790a50cf606602a5ee48108 192.168.31.227:7008 192.168.31.187:7001
检查加入状况:
四、删除node
先用resharding将数据都移除到其余节点,确保node为空以后,才能执行remove操做
先将slot移空
移空后执行删除:
redis-trib.rb del-node 192.168.31.187:7001 bd5a40a6ddccbd46a0f4a2208eb25d2453c2a8db
2个是1365,1个是1366
当你清空了一个master的hashslot时,redis cluster就会自动将其slave挂载到其余master上去
这个时候就只要删除掉master就能够了
四、slave的自动迁移
---------为何要存在冗余slave
好比如今有10个master,每一个有1个slave,而后新增了3个slave做为冗余,有的master就有2个slave了,有的master出现了salve冗余
若是某个master的slave挂了,那么redis cluster会自动迁移一个冗余的slave给那个master
只要多加一些冗余的slave就能够了
为了不的场景,就是说,若是你每一个master只有一个slave,万一说一个slave死了,而后很快,master也死了,那可用性仍是下降了
可是若是你给整个集群挂载了一些冗余slave,那么某个master的slave死了,冗余的slave会被自动迁移过去,做为master的新slave,此时即便那个master也死了
仍是有一个slave会切换成master的
以前有一个master是有冗余slave的,直接让其余master其中的一个slave死掉,而后看有冗余slave会不会自动挂载到那个master
自动化迁移后:
五、redis cluster的核心原理分析:gossip通讯、jedis smart定位、主备切换
1、节点间的内部通讯机制
一、基础通讯原理
(1)redis cluster节点间采起gossip协议进行通讯
跟集中式不一样,不是将集群元数据(节点信息,故障,等等)集中存储在某个节点上,而是互相之间不断通讯,保持整个集群全部节点的数据是完整的
维护集群的元数据用得,集中式,一种叫作gossip
集中式:好处在于,元数据的更新和读取,时效性很是好,一旦元数据出现了变动,当即就更新到集中式的存储中,其余节点读取的时候当即就能够感知到; 很差在于,全部的元数据的跟新压力所有集中在一个地方,可能会致使元数据的存储有压力
gossip:好处在于,元数据的更新比较分散,不是集中在一个地方,更新请求会陆陆续续,打到全部节点上去更新,有必定的延时,下降了压力; 缺点,元数据更新有延时,可能致使集群的一些操做会有一些滞后
咱们刚才作reshard,去作另一个操做,会发现说,configuration error,达成一致
(2)10000端口
每一个节点都有一个专门用于节点间通讯的端口,就是本身提供服务的端口号+10000,好比7001,那么用于节点间通讯的就是17001端口
每隔节点每隔一段时间都会往另外几个节点发送ping消息,同时其余几点接收到ping以后返回pong
(3)交换的信息
故障信息,节点的增长和移除,hash slot信息,等等
二、gossip协议
gossip协议包含多种消息,包括ping,pong,meet,fail,等等
meet: 某个节点发送meet给新加入的节点,让新节点加入集群中,而后新节点就会开始与其余节点进行通讯
redis-trib.rb add-node
其实内部就是发送了一个gossip meet消息,给新加入的节点,通知那个节点去加入咱们的集群
ping: 每一个节点都会频繁给其余节点发送ping,其中包含本身的状态还有本身维护的集群元数据,互相经过ping交换元数据
每一个节点每秒都会频繁发送ping给其余的集群,ping,频繁的互相之间交换数据,互相进行元数据的更新
pong: 返回ping和meet,包含本身的状态和其余信息,也能够用于信息广播和更新
fail: 某个节点判断另外一个节点fail以后,就发送fail给其余节点,通知其余节点,指定的节点宕机了
三、ping消息深刻
ping很频繁,并且要携带一些元数据,因此可能会加剧网络负担
每一个节点每秒会执行10次ping,每次会选择5个最久没有通讯的其余节点
固然若是发现某个节点通讯延时达到了cluster_node_timeout / 2,那么当即发送ping,避免数据交换延时过长,落后的时间太长了
好比说,两个节点之间都10分钟没有交换数据了,那么整个集群处于严重的元数据不一致的状况,就会有问题
因此cluster_node_timeout能够调节,若是调节比较大,那么会下降发送的频率
每次ping,一个是带上本身节点的信息,还有就是带上1/10其余节点的信息,发送出去,进行数据交换
至少包含3个其余节点的信息,最多包含总节点-2个其余节点的信息
-------------------------------------------------------------------------------------------------------
2、面向集群的jedis内部实现原理
开发,jedis,redis的java client客户端,redis cluster,jedis cluster api
jedis cluster api与redis cluster集群交互的一些基本原理
一、基于重定向的客户端
redis-cli -c,自动重定向
(1)请求重定向
客户端可能会挑选任意一个redis实例去发送命令,每一个redis实例接收到命令,都会计算key对应的hash slot
若是在本地就在本地处理,不然返回moved给客户端,让客户端进行重定向
cluster keyslot mykey,能够查看一个key对应的hash slot是什么
用redis-cli的时候,能够加入-c参数,支持自动的请求重定向,redis-cli接收到moved以后,会自动重定向到对应的节点执行命令
(2)计算hash slot
计算hash slot的算法,就是根据key计算CRC16值,而后对16384取模,拿到对应的hash slot
用hash tag能够手动指定key对应的slot,同一个hash tag下的key,都会在一个hash slot中,好比set mykey1:{100}和set mykey2:{100}
(3)hash slot查找
节点间经过gossip协议进行数据交换,就知道每一个hash slot在哪一个节点上
二、smart jedis
(1)什么是smart jedis
基于重定向的客户端,很消耗网络IO,由于大部分状况下,可能都会出现一次请求重定向,才能找到正确的节点
因此大部分的客户端,好比java redis客户端,就是jedis,都是smart的
本地维护一份hashslot -> node的映射表,缓存,大部分状况下,直接走本地缓存就能够找到hashslot -> node,不须要经过节点进行moved重定向
(2)JedisCluster的工做原理
在JedisCluster初始化的时候,就会随机选择一个node,初始化hashslot -> node映射表,同时为每一个节点建立一个JedisPool链接池
每次基于JedisCluster执行操做,首先JedisCluster都会在本地计算key的hashslot,而后在本地映射表找到对应的节点
若是那个node正好仍是持有那个hashslot,那么就ok; 若是说进行了reshard这样的操做,可能hashslot已经不在那个node上了,就会返回moved
若是JedisCluter API发现对应的节点返回moved,那么利用该节点的元数据,更新本地的hashslot -> node映射表缓存
重复上面几个步骤,直到找到对应的节点,若是重试超过5次,那么就报错,JedisClusterMaxRedirectionException
jedis老版本,可能会出如今集群某个节点故障还没完成自动切换恢复时,频繁更新hash slot,频繁ping节点检查活跃,致使大量网络IO开销
jedis最新版本,对于这些过分的hash slot更新和ping,都进行了优化,避免了相似问题
(3)hashslot迁移和ask重定向
若是hash slot正在迁移,那么会返回ask重定向给jedis
jedis接收到ask重定向以后,会从新定位到目标节点去执行,可是由于ask发生在hash slot迁移过程当中,因此JedisCluster API收到ask是不会更新hashslot本地缓存
已经能够肯定说,hashslot已经迁移完了,moved是会更新本地hashslot->node映射表缓存的
-------------------------------------------------------------------------------------------------------
3、高可用性与主备切换原理
redis cluster的高可用的原理,几乎跟哨兵是相似的
一、判断节点宕机
若是一个节点认为另一个节点宕机,那么就是pfail,主观宕机
若是多个节点都认为另一个节点宕机了,那么就是fail,客观宕机,跟哨兵的原理几乎同样,sdown,odown
在cluster-node-timeout内,某个节点一直没有返回pong,那么就被认为pfail
若是一个节点认为某个节点pfail了,那么会在gossip ping消息中,ping给其余节点,若是超过半数的节点都认为pfail了,那么就会变成fail
二、从节点过滤
对宕机的master node,从其全部的slave node中,选择一个切换成master node
检查每一个slave node与master node断开链接的时间,若是超过了cluster-node-timeout * cluster-slave-validity-factor,那么就没有资格切换成master
这个也是跟哨兵是同样的,从节点超时过滤的步骤
三、从节点选举
哨兵:对全部从节点进行排序,slave priority,offset,run id
每一个从节点,都根据本身对master复制数据的offset,来设置一个选举时间,offset越大(复制数据越多)的从节点,选举时间越靠前,优先进行选举
全部的master node开始slave选举投票,给要进行选举的slave进行投票,若是大部分master node(N/2 + 1)都投票给了某个从节点,那么选举经过,那个从节点能够切换成master
从节点执行主备切换,从节点切换为主节点
四、与哨兵比较
整个流程跟哨兵相比,很是相似,因此说,redis cluster功能强大,直接集成了replication和sentinal的功能
----------------------------------------------------------------------------------------------------
没有办法去给你们深刻讲解redis底层的设计的细节,核心原理和设计的细节,
那个除非单独开一门课,redis底层原理深度剖析,redis源码对于我们这个架
构课来讲,主要关注的是架构,不是底层的细节,对于架构来讲,核心的原理
的基本思路,是要梳理清晰的。
----------------------------------------------------------------------------------------------------
咱们以前的三十讲,主要是在讲解redis如何支撑海量数据、高并发读写、高可用服务的架构,redis架构。redis架构,在咱们的真正相似商品详情页读高并发的系统中,redis就是底层的缓存存储的支持。
从这一讲开始,咱们正式开始作业务系统的开发亿级流量以上的电商网站的商品详情页的系统,商品详情页系统,大量的业务,十几我的作一两年,堆出来复杂的业务系统
几十个小时的课程,讲解复杂的业务,把总体的架构给你们讲解清楚,而后浓缩和精炼里面的业务,提取部分业务,作一些简化,把整个详情页系统的流程跑出来。
架构,骨架,有少许的业务,血和肉,把整个项目串起来,在业务背景下,去学习架构。
讲解商品详情页系统,缓存架构,90%大量的业务代码(没有什么技术含量),10%的最优技术含量的就是架构,上亿流量,每秒QPS几万,上十万的,读并发,缓存架构
架构理解:
采用三级缓存:nginx本地缓存+redis分布式缓存+tomcat堆缓存的多级缓存架构
时效性要求很是高的数据:库存
通常来讲,显示的库存,都是时效性要求会相对高一些,由于随着商品的不断的交易,库存会不断的变化。
固然,咱们就但愿当库存变化的时候,尽量更快将库存显示到页面上去,而不是说等了很长时间,库存才反应到页面上去。
时效性要求不高的数据:时效性要求不高的数据:商品的基本信息(名称、颜色、版本、规格参数,等等)。
时效性高:商品价格/库存等时效性要求高的数据,并且种类较少,采起相关的服务系统每次发生了变动的时候,直接采起数据库和redis缓存双写的方案,这样缓存的时效性最高。
时效性不高:商品基本信息等时效性不高的数据,并且种类繁多,来自多种不一样的系统,采起MQ异步通知的方式,写一个数据生产服务,监听MQ消息,而后异步拉取服务的数据,更新tomcat jvm缓存+redis缓存
---------------------------------------------------------------------------------
nginx+lua脚本作页面动态生成的工做,每次请求过来,优先从nginx本地缓存中提取各类数据,结合页面模板,生成须要的页面若是nginx本地缓存过时了,那么就从nginx到redis中去拉取数据,更新到nginx本地
若是redis中也被LRU算法清理掉了,那么就从nginx走http接口到后端的服务中拉取数据,数据生产服务中,如今本地tomcat里的jvm堆缓存中找,ehcache,若是也被LRU清理掉了,那么就从新发送请求到源头的服务中去拉取数据,而后再次更新tomcat堆内存缓存+redis缓存,并返回数据给nginx,nginx缓存到本地
---------------------------------------------------------------------------------
二、多级缓存架构中每一层的意义
nginx本地缓存,抗的是热数据的高并发访问,通常来讲,商品的购买老是有热点的,好比天天购买iphone、nike、海尔等知名品牌的东西的人,老是比较多的
这些热数据,利用nginx本地缓存,因为常常被访问,因此能够被锁定在nginx的本地缓存内
大量的热数据的访问,就是常常会访问的那些数据,就会被保留在nginx本地缓存内,那么对这些热数据的大量访问,就直接走nginx就能够了
那么大量的访问,直接就能够走到nginx就好了,不须要走后续的各类网络开销了
redis分布式大规模缓存,抗的是很高的离散访问,支撑海量的数据,高并发的访问,高可用的服务
redis缓存最大量的数据,最完整的数据和缓存,1T+数据; 支撑高并发的访问,QPS最高到几十万; 可用性,很是好,提供很是稳定的服务
nginx本地内存有限,也就能cache住部分热数据,除了各类iphone、nike等热数据,其余相对不那么热的数据,可能流量会常常走到redis那里
利用redis cluster的多master写入,横向扩容,1T+以上海量数据支持,几十万的读写QPS,99.99%高可用性,那么就能够抗住大量的离散访问请求
tomcat jvm堆内存缓存,主要是抗redis大规模灾难的,若是redis出现了大规模的宕机,致使nginx大量流量直接涌入数据生产服务,那么最后的tomcat堆内存缓存至少能够再抗一下,不至于让数据库直接裸奔
同时tomcat jvm堆内存缓存,也能够抗住redis没有cache住的最后那少许的部分缓存
在请求进行读和更新时候,对于缓存的操做是如何进行的:
读:先读缓存,无则进入数据库,而后更新缓存;
更新:删除缓存,更新数据库
一:不优先删除缓存的状况下,写入数据后,若是再清空缓存若是出现问题,则此时会出现不一致问
先产缓存 在删除
读写并发读写的时候可能出现下面这种双写不一致的问题:
在读并发很低的状况,不多的状况会出现这种双写不一致问题,若是天天商议的流量,则会可能出现不一致状况;
解决方案【创建串行写读队列】:
对读写串行队列须要考虑读的状况下,读的操做可能会hang的太久,须要根据业务场景进行测试;
继续补充中。。。。。