一、Redis-Sentinel(哨兵)
1、介绍
Redis-Sentinel是redis官方推荐的高可用性解决方案,
当用redis作master-slave的高可用时,如果master本身宕机,redis本身或者客户端都没有实现主从切换的功能。
而redis-sentinel就是一个独立运行的进程,用于监控多个master-slave集群,
自动发现master宕机,进行自动切换slave > master。
sentinel主要功能如下:
1. 不时的监控redis是否良好运行,如果节点不可达就会对节点进行下线标识
2. 如果被标识的是主节点,sentinel就会和其他的sentinel节点“协商”,如果其他节点也人为主节点不可达,
就会选举一个sentinel节点来完成自动故障转移
3. 在master-slave进行切换后,master_redis.conf、slave_redis.conf和sentinel.conf的内容都会发生改变,
即master_redis.conf中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换
2、工作原理
每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。 如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。 当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线 在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO 命令 当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次 若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。 若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。 主观下线和客观下线 主观下线:Subjectively Down,简称 SDOWN,指的是当前 Sentinel 实例对某个redis服务器做出的下线判断。 客观下线:Objectively Down, 简称 ODOWN,指的是多个 Sentinel 实例在对Master Server做出 SDOWN 判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断,然后开启failover. SDOWN适合于Master和Slave,只要一个 Sentinel 发现Master进入了ODOWN, 这个 Sentinel 就可能会被其他 Sentinel 推选出, 并对下线的主服务器执行自动故障迁移操作。 ODOWN只适用于Master,对于Slave的 Redis 实例,Sentinel 在将它们判断为下线前不需要进行协商, 所以Slave的 Sentinel 永远不会达到ODOWN。
3、master宕机处理
如果master宕机,我们应该先选一个slave出来,让他成为新的master,其他redis都修改成这个新的master的slave,
但是redis本身或者客户端都没有实现主从切换的功能,当然,人为地修改配置文件,实现上图的功能也是可以的,
但是如果是在深夜,所有人都睡觉了呢,谁来修改配置信息?
这个时候就可以使用redis的Sentinel功能了,它就是实现了,当发现master宕机,自动帮我们去修改其他redis配置文件,
选举出一个新master。
4、Sentinel功能实现图
5、redis一些查看命令
redis-cli info # 查看redis数据库信息 redis-cli info replication # 查看redis的复制授权信息(主从复制) redis-cli info sentinel # 查看redis的哨兵信息
6、Redis主从配置
1.准备三个redis实例,一主两从 # redis-6379.conf配置 port 6379 daemonize yes logfile "6379.log" dbfilename "dump-6379.rdb" dir "/var/redis/data/" # redis-6380.conf配置 port 6380 daemonize yes logfile "6380.log" dbfilename "dump-6380.rdb" dir "/var/redis/data/" slaveof 127.0.0.1 6379 # redis-6381.conf配置 port 6381 daemonize yes logfile "6381.log" dbfilename "dump-6381.rdb" dir "/var/redis/data/" slaveof 127.0.0.1 6379 2. 准备好了三个数据库实例,启动三个数据库实例 # 启动前记得先去创建redis数据存放的文件夹 mkdir -p /var/redis/data/ # 启动实例 redis-server redis-6379.conf redis-server redis-6380.conf redis-server redis-6381.conf # 查看redis服务是否已经启动 ps -ef | grep redis 3. 确定主从关系 redis-cli -p 6379 info replication # Replication role:master connected_slaves:2 slave0:ip=127.0.0.1,port=6380,state=online,offset=336,lag=0 slave1:ip=127.0.0.1,port=6381,state=online,offset=336,lag=1 redis-cli -p 6380 info replication # Replication role:slave master_host:127.0.0.1 master_port:6379
7、Redis Sentinel安装配置
1. Sentinel配置解析 port 26379 // Sentinel的端口 dir /var/redis/data/ // Sentinel日志文件存放位置 logfile "26379.log" // Sentinel日志文件名字 // 当前Sentinel节点监控 127.0.0.1:6379 这个主节点 // 2代表判断主节点失败至少需要2个Sentinel节点节点同意 // mymaster是主节点的别名 sentinel monitor mymaster 127.0.0.1 6379 2 // 每个Sentinel节点都要定期PING命令来判断Redis数据节点和其余Sentinel节点是否可达 // 如果超过30000毫秒30s且没有回复,则判定不可达 sentinel down-after-milliseconds mymaster 30000 // 当Sentinel节点集合对主节点故障判定达成一致时,Sentinel领导者节点会做故障转移操作,选出新的主节点, // 原来的从节点会向新的主节点发起复制操作,限制每次向新的主节点发起复制操作的从节点个数为1 sentinel parallel-syncs mymaster 1 //故障转移超时时间为180000毫秒 sentinel failover-timeout mymaster 180000 // 后台执行 daemonize yes 2. 准备三个哨兵,开始监控主从架构 # 哨兵配置文件redis-26379.conf port 26379 dir /var/redis/data/ logfile "26379.log" sentinel monitor zbjmaster 127.0.0.1 6379 2 sentinel down-after-milliseconds zbjmaster 30000 sentinel parallel-syncs zbjmaster 1 sentinel failover-timeout zbjmaster 180000 daemonize yes # 哨兵配置文件redis-26380.conf port 26380 dir /var/redis/data/ logfile "26380.log" sentinel monitor zbjmaster 127.0.0.1 6379 2 sentinel down-after-milliseconds zbjmaster 30000 sentinel parallel-syncs zbjmaster 1 sentinel failover-timeout zbjmaster 180000 daemonize yes # 哨兵配置文件redis-26381.conf port 26381 dir /var/redis/data/ logfile "26381.log" sentinel monitor zbjmaster 127.0.0.1 6379 2 sentinel down-after-milliseconds zbjmaster 30000 sentinel parallel-syncs zbjmaster 1 sentinel failover-timeout zbjmaster 180000 daemonize yes 3. 启动三个哨兵实例 redis-sentinel redis-26379.conf redis-sentinel redis-26380.conf redis-sentinel redis-26381.conf 注意!!如果发现实验不成功,需删掉所有的哨兵配置文件,从新来过 注意!!如果发现实验不成功,需删掉所有的哨兵配置文件,从新来过 注意!!如果发现实验不成功,需删掉所有的哨兵配置文件,从新来过 # 检查哨兵状态是否正常 # 只有发现如下信息,即为正常 redis-cli -p 26379 info sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 # 最重要的一句 master0:name=zbjmaster,status=ok,address=127.0.0.1:6380,slaves=2,sentinels=3 4. 测试哨兵的自动主从切换 1,干掉6379的redis数据库 kill -9 6379的PID 2,查看6380和6381的身份信息,是否自动的进行主从切换 我们设置的是30s后master没有响应,哨兵自动进行主从切换,因此30s后查看主从信息 redis-cli -p 6380 info replication redis-cli -p 6381 info replication 3,手动启动6379挂掉的数据库,查看是否会被哨兵,添加进信息的主从集群 redis-server redis-6379.conf redis-cli -p 6379 info replication
二、redis分区和集群
1、什么是分区和集群
1. 分区
分区是分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集。
分区可以让Redis管理更大的内存,Redis将可以使用所有机器的内存。如果没有分区,你最多只能使用一台机器的内存。
分区使Redis的计算能力通过简单地增加计算机得到成倍提升,Redis的网络带宽也会随着计算机和网卡的增加而成倍增长。
2. 集群
redis集群就是分区的一种的实现
2、为什么要用分区
1. 并发问题
官方声称 redis 每秒可以执行10万条命令
但是假如业务需要每秒100万的命令执行呢(例如新浪微博某某明星出轨、官宣之类的)
2. 数据量
当数据量太大的时候,一台服务器内存正常是16~256G,假如你的业务需要500G内存,怎么办?
3. 解决方案
方案一:
配置一台超级牛逼的服务器,拥有超大内存和超强的cpu,
但是这么做的成本是非常高的,而且,万一这台机器宕掉了,那你的服务还不是全挂了。
方案二:
考虑分布式,加机器,把数据分到不同的位置,分摊集中式的压力,一堆机器做一件事。
3、分区的数据分布理论
redis是一个非关系型数据库,它的存储是key-value形式的,
redis实例集群主要思想是将redis数据的key进行散列,通过hash函数特定的key会映射到指定的redis节点上
分布式数据库首要解决把整个数据集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整个数据的一个子集。
常见的分区规则有哈希分区和顺序分区。
4、顺序分区
假设我有三个节点,100个redis的数据,按照平均值(几乎是平均的),顺序分区的规则就是:
把1-33个数据 放在 node1
把34-66个数据 放在node2
把67-100个数据 放在node3
5、哈希分区
1. 哈希分区的规则
1, 节点取余分区
2, 一致性哈希分区
3, 虚拟槽分区(redis-cluster采用的方式)
2. 节点取余
例如按照节点取余的方式,分三个节点
1~100的数据对3取余,可以分为三类
余数为0
余数为1
余数为2
把余数为0的数据存到同一个节点
把余数为1的数据存到同一个节点
把余数为2的数据存到同一个节点
那么同样的分4个节点就是hash(key)%4,余数相同的存到同一个节点
节点取余的优点是简单,客户端分片直接是哈希+取余
3. 一致性哈希
客户端进行分片,哈希+顺时针取余
4. 虚拟槽分区
本文研究哈希分区之虚拟槽分区,因此下面单独来聊一聊
三、哈希分区之虚拟槽分区
1、介绍
Redis Cluster采用的就是虚拟槽分区
虚拟槽分区巧妙地使用了哈希空间,使用分散度良好的哈希函数把所有的数据映射到一个固定范围内的整数集合,
这些整数就定义为槽(slot)。
Redis Cluster槽的范围是0 ~ 16383,即一共16384个槽。
槽是集群内数据管理和迁移的基本单位。采用大范围的槽的主要目的是为了方便数据的拆分和集群的扩展,
每个节点(redis实例)负责一定数量的槽。
2、虚拟槽图解
3、搭建redis cluster
redis支持多实例的功能,我们在单机演示集群搭建,需要6个实例,三个是主节点,三个是从节点,数量为6个节点才能保证高可用的集群。
1.准备6个节点,用于存储数据,分配槽位,每个节点的配置,如下,仅仅是端口的区别 # redis-7000.conf配置 port 7000 daemonize yes dir "/opt/redis/data" logfile "7000.log" dbfilename "dump-7000.rdb" cluster-enabled yes cluster-config-file nodes-7000.conf 其余5个配置跟上面一模一样,仅仅是端口的区别 # redis-7001.conf配置 # redis-7002.conf配置 # redis-7003.conf配置 # redis-7004.conf配置 # redis-7005.conf配置 注意:要创建存放日志的文件夹 mkdir -p /opt/redis/data 2.启动6个数据库实例 redis-server redis-7000.conf redis-server redis-7001.conf redis-server redis-7002.conf redis-server redis-7003.conf redis-server redis-7004.conf redis-server redis-7005.conf 3.开始分配redis集群状态,以及槽位分配 Redis Cluster本身提供了自动将数据分散到Redis Cluster不同节点的能力, 但是槽位的分配就比较麻烦了,当然了,如果你是大神,你完全可以自定义槽位的分配, 一些大神已经写好了槽位分配的工具或脚本了,例如豆瓣公司开源的codis工具,还有ruby语言的作者,写的redsi.rb, 因此我们可以使用一些工具帮我们进行redis cluster的搭建 4.通过ruby脚本,一键创建redis-cluster,进行槽位分配 5.准备ruby的编程环境 1,下载ruby的源码包 wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz 2,解压缩ruby远吗 tar -zxvf ruby-2.3.1.tar.gz 3,开始编译安装ruby 进入ruby源码包 ./configure --prefix=/opt/ruby/ 4,开始编译且编译安装 make && make install 5,配置ruby的环境变量 vim /etc/profile 写入如下配置 PATH=你原本的PATH:/opt/ruby/bin source /etc/profile 6.安装ruby操作redis的模块 1,下载ruby操作redis的模块 wget http://rubygems.org/downloads/redis-3.3.0.gem 2,安装 gem install -l redis-3.3.0.gem 3,搜索创建redis集群的命令 find /opt -name redis-trib.rb /opt/redis-4.0.10/src/redis-trib.rb 7.一键创建redis集群 /opt/redis-4.0.10/src/redis-trib.rb create --replicas 1 127.0.0.1:7000 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 --replicas 进行身份授权 后面的1 代表,每个主节点,只有一个从节点 默认将 7000 7001 70002 设置为主库 将7003 7004 7005 设置为从库 8.检查集群状态 redis-cli -p 7000 cluster info 9.测试集群节点,看是否能正常写入数据 redis-cli -c -p 7000 -p 指定数据库端口 -c 指定开启集群模式 set age 18 # 设置一个key会自动分配槽位,重定向到槽位所在的节点即代表成功 在任意一个节点都可以get age,会自动重定向到 age 所在的节点。 10.redis-cluster 会默认将不同的key,进行CRC16算法,进行分配到不同槽位 11.数据正常重定向,即redis集群ok
四、docker入门
1、介绍
1. 什么是docker
Docker 最初是 daoCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,于 2013 年 3 月以 Apache 2.0 授权协议开源,主要项目代码在 GitHub 上进行维护。
Docker 使用 Google 公司推出的 Go 语言 进行开发实现。
docker是linux容器的一种封装,提供简单易用的容器使用接口。它是最流行的Linux容器解决方案。
docker的接口相当简单,用户可以方便的创建、销毁容器。
docker将应用程序与程序的依赖,打包在一个文件里面。运行这个文件就会生成一个虚拟容器。
程序运行在虚拟容器里,如同在真实物理机上运行一样,有了docker,就不用担心环境问题了
2.docker应用场景
web应用的自动化打包和发布
自动化测试和持续集成、发布
在服务型环境中部署和调整数据库或其他应用
2、为什么要用docker
首先要知道在实际中,我们如何解决项目部署的环境配置的问题呢?
1. 解决方案1,使用虚拟机
使用vmware的克隆功能,vmware支持一个模板克隆
首先准备一个vmware系统模板,装好一些必要的环境,例如:python3 mysql redis nginx等等,
然后基于这个模板,克隆生成新的系统,在新的系统上可以根据项目需要的继续配置不同的环境,
也就是,基于同一个镜像,同一个系统模板,可以生成 N 个系统实例。
但是但是虚拟化也是有局限性的,每一个虚拟机都是一个完整的操作系统,要分配系统资源,虚拟机多道一定程度时,操作系统本身资源也就消耗殆尽,或者说必须扩容
虚拟机的缺点:
1,资源占用多
虚拟机会独占一部分内存和硬盘空间。它运行的时候,其他程序就不能使用这些资源了。哪怕虚拟机里面的应用程序,真正使用的内存只有 1MB,虚拟机依然需要几百 MB 的内存才能运行。
2,冗余步骤多
虚拟机是完整的操作系统,一些系统级别的操作步骤,往往无法跳过,比如用户登录。
3,启动慢
启动操作系统需要多久,启动虚拟机就需要多久。可能要等几分钟,应用程序才能真正运行。
2. 解决方案2,使用linux容器
Linux容器不是模拟一个完整的操作系统,而是对进程进行隔离。在正常进程的外面套了一个保护层,对于容器里面进程来说,它接触的资源都是虚拟的,从而实现和底层系统的隔离。
docker是linux的一种容器。
优点
1,启动快
容器里面的应用,直接就是底层系统的一个进程,而不是虚拟机内部的进程。所以,启动容器相当于启动本机的一个进程,而不是启动一个操作系统,速度就快很多。
2,资源占用少
容器只占用需要的资源,不占用那些没有用到的资源;虚拟机由于是完整的操作系统,不可避免要占用所有资源。另外,多个容器可以共享资源,虚拟机都是独享资源。
3,体积小
容器只要包含用到的组件即可,而虚拟机是整个操作系统的打包,所以容器文件比虚拟机文件要小很多。
总之,容器有点像轻量级的虚拟机,能够提供虚拟化的环境,但是成本开销小得多。
3、docker与传统虚拟机对比
特性 | 容器 | 虚拟机 |
启动 | 秒级 | 分钟级 |
硬盘使用 | 一般为MB | 一般为GB |
性能 | 接近原生 | 弱 |
系统支持量 | 单机支持上千个容器 | 一般几十个 |
4、虚拟机和docker容器的架构
1. 虚拟机
2. 容器
3. 虚拟机+容器
docker的每个容器都相当于一个微型的操作系统,它占用的资源非常少,
因此在一个系统上可以开启非常多的docker实例。
五、Docker的初步使用
1、docker三大概念
镜像 image
容器 container
仓库 repository
docker整个生命周期就是这三个概念
1. docker镜像(image) Docker镜像就是一个只读的模板。 例如:一个镜像可以包含一个完整的CentOS操作系统环境,里面仅安装了Apache或用户需要的其他应用程序。 就相当于我们以前买的那些dvd装机的碟,你用这个碟可以给你的电脑装上win7 10 等系统,系统自带了一些软件, 暴风影音,QQ等,然后装好系统后,我们需要什么,我们还能自己下载,比如LOL、跑跑卡丁车之类的。 有了镜像后,就可以用镜像来创建Docker容器。 Docker提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经做好的镜像来直接使用。 镜像的分层存储 因为镜像包含完整的root文件系统,体积是非常庞大的,因此docker在设计时按照Union FS的技术,将其设计为分层存储的架构。 镜像不是ISO那种完整的打包文件,镜像只是一个虚拟的概念,他不是一个完整的文件,而是由一组文件组成,或者多组文件系统联合组成 2. docker容器(container) image和container的关系,就像面向对象程序设计中的 类和实例一样,镜像是静态的类(class),容器是镜像运行时的实体(实例化的对象object) Docker利用容器来运行应用。 容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的,保证安全的平台。 可以把容器看做是一个简易版的Linux环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。 镜像 容器实例1=镜像() 容器实例2=镜像() 容器实例3=镜像() 容器实例4=镜像() 容器实例5=镜像() 注意:镜像是只读的,容器在启动的时候创建一层可写层作为最上层。 3. docker仓库(repository) 仓库是集中存放镜像文件的场所。有时候把仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。 实际上,仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。 仓库分为公开仓库(Public)和私有仓库(Private)两种形式。 最大的公开仓库是Docker Hub,存放了数量庞大的镜像供用户下载。国内的公开仓库包括Docker Pool等,可以提供大陆用户更稳定快读的访问。 当用户创建了自己的镜像之后就可以使用push命令将它上传到公有或者私有仓库,这样下载在另外一台机器上使用这个镜像时候,只需需要从仓库上pull下来就可以了。 注意:Docker仓库的概念跟Git类似,注册服务器可以理解为GitHub这样的托管服务。
2、CentOS安装docker
总结官方教程如下
1.卸载旧版本 sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-selinux \ docker-engine-selinux \ docker-engine 2.设置存储库 sudo yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo 3.安装docker社区版 sudo yum install docker-ce 4.启动关闭docker systemctl start/stop/restart/status docker 5.确认docker以及启动 docker version
3、Docker镜像加速器
修改docker的镜像加速器,daocloud公司推出的加速工具 1.一句命令生成docker加速地址 curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://f1361db2.m.daocloud.io 2.好像有一个坑,请修改配置文件 /etc/docker/daemon.json 改成如下配置即可(默认在最后有个逗号,去掉即可,如果没有,请忽略以下步骤) {"registry-mirrors": ["http://f1361db2.m.daocloud.io"]} 3.重启docker systemctl restart docker
4、注意
docker容器必须有后台进程在运行,如果docker容器内没有任务在运行中,容器就退出
docker容器必须有后台进程在运行,如果docker容器内没有任务在运行中,容器就退出
docker容器必须有后台进程在运行,如果docker容器内没有任务在运行中,容器就退出
5、docker的基本示例
1. 示例1
docker search hello-docker # 搜索docker镜像 ,就是去 docker hub搜索 hello-docker docker pull hello-world # 下载公网的,docker镜像 docker image ls # 查看本地的镜像有哪些 docker images # 这两条命令一样的,docker进行了很多的命令升级,不用慌 docker run hello-world # 运行一个docker镜像,产生一个容器实例 docker container ls # 列出所有正在运行的容器(因为hello world一跑完就退出了,一退出,容器也就退出了) docker ps -a # 列出所有曾经运行过的容器记录,以及正在运行的容器记录 CONTAINER ID IMAGE COMMAND CREATED STATUS 容器ID 镜像 命令 创建时间 状态
2. 示例2
docker pull centos # 下载cnetos镜像 # 运行一个在后台的任务 docker run -d centos /bin/sh -c "while true;do echo hello-docker; sleep 1;done" -d # 后台运行容器 /bin/sh # 指定使用centos的bash解释器 -c # 运行一段shell命令 "while true;do echo hello-docker; sleep 1;done" # 在linux后台,每秒中打印一个hello-docker docker ps -a # 列出所有曾经运行过的容器记录,以及正在运行的容器记录 docker logs -f 容器id #不间断打印容器的日志信息 # 容器是有自己的微型操作系统的。微型linux docker exec -it ee0 /bin/bash exec # 进入容器的参数 -i # 交互式的操作容器 -t # 开启一个terminel终端,用于和linux交互 ee0 # docker容器的id /bin/bash # 指定docker容器,用shell解释器交互 exit # 退出容器terminel终端 docker run -it centos /bin/bash # 创建一个新的容器,且以交互式的方式进入容器 docker stop 容器id # 停止这个容器的运行 docker kill 容器id # 停止这个容器的运行 docker rm 容器id # 删除这个容器