redis

一:缓存概念

缓存是为了调节速度不一致的两个或多个不同物质的速度,在中间对速度较快的一方起到一个加速访问速度较慢的一方的作用,比如cpu的一级、二级缓存是保存了cpu最近经常访问的数据,内存是保存了cpu经常访问硬盘的数据,而且硬盘也有大小不一的缓存,甚至是物理服务器的raid卡也有缓存,都是为了起到加速cpu访问硬盘数据的目的,因为cpu的速度太快了,cpu需要的数据由于硬盘往往不能在短时间内满足cpu的需求,因此cpu缓存、内存、Raid卡缓存以及硬盘缓存就在一定程度上满足了cpu数据需求,即cpu从缓存读取数据可以大幅提高cpu的工作效率

在这里插入图片描述

1.1:系统缓存

1.1.1:buffer与cache

buffer:缓冲也叫写缓冲,一般用于写操作,可以将数据先写入内存在写入磁盘,buffer一般用于写缓冲,用于解决不同介质的速度不一致的缓冲,先将数据临时写入到离自己最近的地方,以提高写入速度,cpu会把数据先写到内存的磁盘缓冲区,然后就认为数据已经写入完成,然后由内核在后续的时间在写入磁盘,所以服务器突然断电会丢失内存中的部分数据

cache:缓存也叫读缓存,一般用于读操作,cpu读文件从内存读,如果内存没有就先从硬盘督导内存在读到cpu,将需要频繁读取的数据放在离自己最近的缓存区域,下次读取的时候即可快速读取

1.1.2:cache的保存位置:

客户端:浏览器

内存:本地服务器、远程服务器

硬盘:本机硬盘、远程服务器硬盘

1.1.3:cache的特性

自动过期:给缓存的数据加上有效时间,超出时间后自动过期删除

过期时间:强制过期,原网站更新图片后CDN不会更新的,需要强制图片缓存过期

命中率:即缓存的读取命中率

1.2:用户层缓存:

1.2.1:DNS缓存

默认为60秒,即60秒之内在访问同一个域名就不再进行dns解析:

查看chrome浏览器的DNS缓存

谷歌浏览器看不了了

1.2.2:火狐浏览器缓存

about:cache

1.2.3:浏览器缓存过期机制:

1.2.3.1:最后修改时间

系统调用文件的时候会获取文件的最后修改时间,如果没有发生变化就返回给浏览器304的状态码,表示没有发生变化,然后浏览器就使用本地的缓存展示资源

在这里插入图片描述

如果服务端返回最后修改时间没有发生过变化,则直接使用浏览器的本地缓存,状态码是304

在这里插入图片描述

1.2.3.2:Etag标记

基于Etag标记是否一致做判断页面是否发生过变化,比如基于Nginx的etag on来实现

在这里插入图片描述

1.2.3.3:过期时间

以上两种都需要发送请求,即不管资源是否过期都要发送请求进行协商,这样会消耗不必要的时间,因此有了缓存的过期时间,即第一次请求资源的时候带一个资源的过期时间,默认为30天,当前这种方式使用的比较多,但是无法保证客户的时间都是准确并且一致的,因此会加入一个最大生存周期,使用用户本地的时间计算缓存数据是否超过多少天,下面的过期时间为2027年,但是缓存的最大生存周期计算为等于3650天,即10年,过期时间如下

在这里插入图片描述

1.3:CDN缓存:

1.3.1:什么是CDN:

内容分发网络(Content Delivery Network),通过将服务内容分发至全网加速节点,利用全球调度系统使用户能够就近获取,有效降低访问延迟,提升服务可用性,CDN第一降低机房的使用宽带,因为很多资源通过CDN直接返回用户了,第二解决不同运营商之间的互联,因为可以让联通的网络访问电信,电信的网络访问联通,起到加速用户访问的目的,第三:解决用户访问的地域问题,就近返回用户资源

百度CDN: https://cloud.baidu.com/product/cdn.html
阿里CDN: https://www.alibabacloud.com/zh/product/content-delivery-network
腾讯CDN: https://www.qcloud.com/product/cdn

1.3.2:用户请求CDN流程:

提前对静态内容进行预缓存,避免大量的请求回源,导致主站网络带宽被打满而导致数据无法更新,另外CDN可以将数据根据访问的热度不同而进行不同级别的缓存,例如访问量最高的资源访问CDN边缘节点的内存,其次的放在SSD或者SATA,再其次放在云存储,这样兼顾了速度与成本

在这里插入图片描述

在这里插入图片描述

1.3.3:CDN主要优势:

提前对静态内容进行预缓存,避免大量的请求回源,导致主站网络带宽被打满而导致数据无法更新,另外CDN可以将数据根据访问的热度不同而进行不同级别的缓存,例如访问量最高的资源访问CDN边缘节点的内存,其次的放在SSD或者SATA,再其次的放在云存储,这样兼顾了速度与成本。缓存-缓存到最快的地方如内存,缓存的数据准确命中率高,访问速度就快

调度准确-将用户调度到最近的边缘节点
性能优化-CDN 专门用于缓存响应速度快
安全相关-抵御攻击
节省带宽:由于用户请求由边缘响应,因此大幅降低到原站带宽

1.4:应用层缓存:

Nginx、PHP等web服务可以设置应用缓存以加速响应用户请求,另外有些解释性语言比如PHP/Python/Java不能直接运行,需要先编译成字节码,但字节码需要解释为机器码之后才能执行,因此字节码也是一种缓存,有时候会出现程序代码上线后字节码没有更新的现象

1.5:其他层面的缓存

1.5.1:CPU缓存

cpu缓存(L1的数据缓存和L1的指令缓存)、二级缓存、三级缓存

在这里插入图片描述

1.5.2:cookie与session:

Cookie是访问某些网站以后在本地存储的一些网站相关的信息,下次再访问的时候减少一些步骤,比如加密后的账户名密码等信息

Cookie是服务器再客户端浏览器上存储的小段文本并随每一个请求发送至同一个服务器,是一种实现客户端保持状态的方案

session称为会话信息,位于web服务器上,主要负责访问者与网站之间的交互,当浏览器请求http地址时,可以基于之前的session实现会话保持session共享等

1.5.3:session与cookie的区别

1、Cookie以文本文件格式存储再浏览器中,而session存储再服务端

2、cookie的存储限制了数据量,只永许4KB,而session时无限制的

3、cookie包含再每一个客户端请求报文中,因此容易被人捕获

4、cookie和session都可以设置过期时间

二:redis部署与使用

2.1:redis基础

官方网址:https://redis.io

Redis和Memcached是非关系型数据库也称为NoSQl数据库,MySQL、Mariadb、SQL Server、PostgreSQL、Oracle数据库属于关系型数据库(RDBMS, Relational Database Management System)

2.1.1:redis简介

Redis(Remote Dictionary Server)再2009年公布,开发者Salvatore Sanfilippo是意大利开发者,他本想为自己公司开发一个用户替换MySQL的产品Redis,但是没有想到他把Redis开源后大受欢迎,短短几年,Redis就有了很大的用户群体,目前国内外使用的公司知乎网、BAT

Redis是一个开源的、遵循BSD协议的、基于内存的而且目前比较流行的键值数据库(key-value database),是一个非关系型数据库,redis提供将内存通过网络远程共享的一种服务,提供类似功能的还有memcache,但相比memcache,redis还提供了易扩展、高性能、具备数据持久性等功能

redis再并发、低延迟环境要求比较高的环境使用量非常广泛

redis 2.4 2.6 2.8-哨兵
	4.0
	5.0 集群管理命令 redis-cli
	6.0 多线程(写还是单线程)

2.1.2:redis对比memcached

支持数据的持久化:可以将内存中的数据保持在磁盘中,重启redis服务或者服务器之后可以从备份文件中恢复数据到内存继续使用

支持更多的数据类型: 支持string(字符串)、hash(哈希数据)、list(列表)、set(集合)、zet(有序集合)
支持数据的备份: 可以实现类似于数据的master-slave模式的数据备份,另外也支持使用快照+AOF。
支持更大的value数据: memcache是多线程,所以单机情况下没有memcache并发高,但redis支持分布式集群以实现更高的并发,单redis实例可以实现数万并发
支持集群横向扩展: 基于redis cluster的横向扩展,可以实现分布式集群,大幅提升性能和数据安全性
都是基于C语言开发

2.1.3:redis典型应用场景:

Session 共享:常见的web集群中的Tomcat或者PHP中多web服务器session共享
消息队列:ELK的日志缓存、部分业务的订阅发布系统
计数器:访问排行榜、商品浏览数等次数相关的数值统计场景
缓存:数据库查询缓存、电商网站商品信息、新闻内容
微博/微信社交场合:共同好友、点赞评论等

2.2:Redis安装及使用

官方下载地址:https://redis.io/download/

2.2.1:yum安装redis

在centos系统上需要安装epel源

2.2.1.1:查看yum仓库redis版本
[root@redis ~]# yum list redis
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirror.lzu.edu.cn
 * epel: mirror.01link.hk
 * extras: mirrors.bupt.edu.cn
 * updates: mirrors.bupt.edu.cn
已安装的软件包
redis.x86_64                                            3.2.12-2.el7                                           
2.2.1.2:安装redis
# yum install -y redis
# systemctl start redis && systemctl enabled redis
[root@redis ~]# redis-cli 
127.0.0.1:6379> info
2.2.1.3:二进制安装
# wget https://download.redis.io/releases/redis-6.2.2.tar.gz
# tar xzf redis-6.2.2.tar.gz
# cd redis-6.2.2


# make USE_SYSTEMD=yes PREFIX=/apps/redis  install

# 
# cp redis.conf  /apps/redis/etc/


# cp utils/systemd-redis_server.service /usr/lib/systemd/system/redis.service 


cat /usr/lib/systemd/system/redis.service
[Unit]
Description=Redis data structure server
Documentation=https://redis.io/documentation
#Before=your_application.service another_example_application.service
#AssertPathExists=/var/lib/redis
Wants=network-online.target
After=network-online.target

[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis.conf --supervised systemd --daemonize no
## Alternatively, have redis-server load a configuration file:
#ExecStart=/usr/local/bin/redis-server /path/to/your/redis.conf
LimitNOFILE=10032
NoNewPrivileges=yes
OOMScoreAdjust=-900
#PrivateTmp=yes
Type=notify
TimeoutStartSec=15 #这一行不改会报错
TimeoutStopSec=15
UMask=0077
User=redis
Group=redis
WorkingDirectory=/apps/redis

[Install]
WantedBy=multi-user.target


创建redis用户和数据目录
groupadd -g 1000 redis && useradd -u 1000 -g 1000 redis -s /sbin/nologin
mkdir  /apps/redis/{etc,logs,data,run}
chown redis.redis -R /usr/local/redis

创建软连接
[root@redis ~]# ln -sv /apps/redis/bin/redis-* /usr/bin/
"/usr/bin/redis-benchmark" -> "/apps/redis/bin/redis-benchmark"
"/usr/bin/redis-check-aof" -> "/apps/redis/bin/redis-check-aof"
"/usr/bin/redis-check-rdb" -> "/apps/redis/bin/redis-check-rdb"
"/usr/bin/redis-cli" -> "/apps/redis/bin/redis-cli"
"/usr/bin/redis-sentinel" -> "/apps/redis/bin/redis-sentinel"
"/usr/bin/redis-server" -> "/apps/redis/bin/redis-server"

#编译安装后的命令
[root@redis ~]# ll /apps/redis/bin/
总用量 18872
-rwxr-xr-x. 1 redis redis 4829936 21 14:06 redis-benchmark #redis性能测试工具
lrwxrwxrwx. 1 redis redis      12 21 14:06 redis-check-aof #AOF文件检查工具
lrwxrwxrwx. 1 redis redis      12 21 14:06 redis-check-rdb #RDB文件检查工具
-rwxr-xr-x. 1 redis redis 5002776 21 14:06 redis-cli #客户端工具
lrwxrwxrwx. 1 redis redis      12 21 14:06 redis-sentinel -> redis-server #哨兵,软连接到server
-rwxr-xr-x. 1 redis redis 9483152 21 14:06 redis-server #redis服务启动命令

2.2.1.4:解决当前的警告提示

2.2.1.4.1:tcp-backlog

backlog参数控制的是三次握手的时候server端收到client ack确认号之后的队列值

net.core.somaxconn=512
2.2.1.4.2:vm.overcommit_memory:

0、表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请永许;否则,内存申请失败,并把错误返回给应用进程

1、表示内核允许分配所有的物理内存,而不管当前的内存状态如何

2、表示内核允许分配超过所有物理内存和交换空间总和的内存

vm.overcommit_memory = 1
2.2.1.4.3:transparent hugepage:

大页内存动态分配,需要关闭让redis负责内存管理

echo never > /sys/kernel/mm/transparent_hugepage/enabled
import redis

pool = redis.ConnectionPool(host="172.16.10.101", port=30063,db=1,password="")
r = redis.Redis(connection_pool=pool)
for i in range(500):
    r.set(name="gf{}".format(i), value="gf-value{}".format(i))

2.3: redis配置文件:

2.3.1:redis主要配置项:

bind 0.0.0.0 #监听地址,可以用空格隔开后多个监听ip

protected-mode yes # redis3.2之后加入的新特性,在没有设置bind IP和密码的时候,redis只允许访问127.0.0.1:6379,远程访问将提示警告并拒绝远程访问

port 6379 #监听端口

tcp-backlog 511 #三次握手的时候server端收到client ack确认号之后的队列值

timeout 0 #客户端和Redis服务端的连接超时时间,默认是0,表示永不超时

tcp-keepalive 300 #tcp 会话保持时间

daemonize no #默认情况下redis不是作为守护进程运行的,如果你想让它在后台运行,你就把它改成yes,当redis作为守护进程运行的时候,他会写一个pid到/var/run/redis.pid文件里面

supervised no #和操作系统相关参数,可以设置通过upstart和systemd管理redis守护进程,centos7以后都使用systemd

pidfile /var/run/redis_6379.pid #pid文件路径

loglevel notice #日志级别

logfile "" #日志路径

databases 16 #设置db库数量,默认16个库

always-show-logo yes #在启动redis时是否显示log


save 900 1 #在900秒内有一个键内容发生更改就触发快照机制
save 300 10
save 60 10000

stop-writes-on-bgsave-error no #快照出错时是否禁止redis写入操作
(redis快照触发快照的同时,在后台生成一个子进程,由子进程dump快照,
快照往磁盘保存失败的时候,是否允许redis写数据)

rdbcompression yes #持久化到RDB文件时,是否压缩,"yes"为压缩,"no"为不压缩

rdbchecksum yes #是否开启RC64校验以保证RDB文件的完整性,默认为开启

dbfilename dump.rdb #快照文件名

rdb-del-sync-files no #在没有开启数据持久化的情况下删除赋值中使用的RDB文件

dir ./ #快照及AOF持久化文件的保存路径

replica-serve-stale-data yes #当从库同主库失去连接或者复制正在进行,从库有两种数据提供方式:
	1. 如果replica-serve-stale-data 设置为yes(默认设置),从库会继续响应客户端的读请求
	2. 如果replica-serve-stale-data 设置为no,除去指定的命令之外的任何请求都会返回一个错误"SYNC with master in progress".
	
replica-read-only yes #是否设置从库只读

repl-diskless-sync no #是否使用socket方式复制数据(无盘同步),新slave连接时需要做数据的全量同步,redis server就要从内存dump出新的RDB文件,然后从master传到slave,有两种方式把RDB文件传输给客户端
	1.基于硬盘(disk-backed): master创建一个新进程dump RDB,RDB完成之后由父进程(即主进程)传给slaves
	2.基于socket(diskless): master创建一个新进程直接dump RDB到slave的socket,不仅过主进程,不经过硬盘
	基于硬盘的花,RDB文件创建后,一旦创建完毕,可以同时服务更多的slave,但是基于socket的话,新的slave连接到master之后得逐个同步数据
	#在磁盘较慢并且网络较快得时候,可以用diskless(yes),否则使用磁盘(no)

repl-diskless-sync-delay 30 #diskless即无盘复制得延迟时间

设置0为关闭等待延迟,如果开启延迟那么在延长时间内新连接得客户端,Redis server会一起通过disk方式同步数据,但是一旦复制开始还没有结束之前,master节点不会再接收新slave得复制请求,知道下一次同步开始。

repl-ping-slave-period 10 #slave根据master指定得时间进行周期性得PING监测

repl-diskless-load disabled #是否使用无盘加载

disabled: #不要使用无磁盘加载,先将rdb文件存储到磁盘
on-empty-db: #只有再完全安全得情况下才使用无磁盘加载
swapdb: #解析时再RAM中保留当前db内容得副本,直接从套接字获取数据

repl-timeout 60 #复制连接的超时时间,需要大于repl-ping-slave-period,否则会经常报超时

repl-disable-tcp-nodelay no #再socket模式下是否再slave套接字发送SYNC之后禁用TCP_NODELAY

如果选择yes,Redis将使用更少的TCP包和带宽来向slaves发送数据**,**但是这将使数据传输到slave上有延迟,linux内核的默认配置会达到40毫秒,如果你选择了 no 数据传输到slave的延迟将会减少但要使用更多的带宽

repl-backlog-size 512mb #复制缓冲区内存大小,只有再slave连接之后才分配内存

repl-backlog-ttl 3600 #多少时间master没有slave连接,就清空backlog缓冲区

replica-priority 100 #当master不可用,Sentinel会根据slave的优先级选举一个master,最低的优先级的slave,最高优先级的为master,而配置为0,永远不会被选举

requirepass foobared #设置redis连接密码

rename-command #重命名一些高危命令

maxclients 10000 #redis最大连接客户端

maxmemory #最大内存,单位为bytes字节,8G内存的计算方式8(G)1024(MB)1024(kb)1024(kbyte),需要注意的是slave的输出缓冲区是不计算再maxmemory内

appendonly no #是否开启AOF日志记录,默认redis使用的是rdb方式持久化,这种方式再许多应用中已经足够用了,但是redis如果中途宕机,会导致可能有几分钟的数据丢失(取绝于dumpd数据的间隔时间),根据save的策略进行持久化,Append Only File是另一种持久化方式,可以提供更好的持久化特性,redis会把每次写入的数据再接收后都写入appendonly.aof文件,每次启动时Redis都会把这个文件的数据读入内存里,先忽略RDB文件

appendfilename “appendonly.aof” #AOF文件名

appendfsync everysec #aof持久化策略的配置,no表示不执行fsync,由操作系统保证数据同步到磁盘,always表示每次写入都执行fsync,以保证数据同步到磁盘,everysec表示每秒执行一次fsync,可能会导致丢失者1s数据

no-appendfsync-on-rewrite no #再aof rewrite期间,是否对aof新纪录的append暂缓使用文件同步策略,主要考虑磁盘IO开支和请求阻塞时间。默认为no,表示"不暂缓",新的aof记录任然会被立即同步,linux的默认fsync策略为30秒,如果为yes 可能丢失30秒数据,但由于yes性能较好而且会避免出现阻塞因此比较推荐

auto-aof-rewrite-percentage 100 #当Aof log增长超过指定百分比例时,重写AOF文件,设置为0表示不自动重写Aof日志,重写是为了使aof体积保持最小,但是还可以确保保存最完整的数据

auto-aof-rewrite-min-size 64mb #触发aof rewrite的最小文件大小

auto-load-truncated yes #是否加载由于其他原因导致的末尾异常的Aof文件(主进程被kill/断电等)

lua-time-limit 5000 #lua脚本的最大执行时间,单位为毫秒

cluster-enabled yes #是否开启集群模式,默认是单机模式

cluster-config-file nodes-6379.conf #由node节点自动生成的集群配置文件

cluster-node-timeout 15000 #集群中node节点连接超时时间

cluster-replica-validity-factor 10 #再执行故障转移的时候可能有些节点和master断开一段时间数据比较旧,这些节点就不适用于选举为master,超过这个时间的就不会被进行故障转移

cluster-migration-barrier 1 #集群迁移屏障,一个主节点拥有的至少正常节点的从节点,即如果主节点的slave节点故障后会将多余的从节点分配到当前主节点成为其新的从节点

cluster-require-full-coverage no #集群请求槽位全部覆盖,如果一个主库宕机且没有备库就会出现集群槽位不全,那么yes情况下redis集群槽位验证不全就不在对外提供服务,而no则可以继续使用但是会出现查询数据查不到的情况(因为有数据丢失)

slow log 是redis用来记录查询执行时间的日志系统,slow log保存再内存里面,读写速度非常快,因此你可以放心得使用它,不必担心因为开启slow log 而损害redis的速度

slowlog-log-slower-than 10000 #以微秒为单位的慢日志记录,为负数会禁用慢日志,为0会记录每个命令操作

slowlog-max-len 128 #记录多少条慢日志保存再队列,超出后会删除最早的,以此滚动删除

127.0.0.1:6379> set name2 gf2
OK
127.0.0.1:6379> SLOWLOG len
(integer) 9
127.0.0.1:6379> SLOWLOG get
1) 1) (integer) 6
   2) (integer) 1707117592
   3) (integer) 1
   4) 1) "SLOWLOG"
      2) "len"
   5) "127.0.0.1:44944"
   6) ""
127.0.0.1:6379> SLOWLOG reset
OK

2.3.2:redis持久化:

redis虽然是一个内存级别的缓存程序,也就是redis是使用内存进行数据的缓存的,但是其可以将内存的数据按照一定的策略保存到硬盘上,从而实现数据持久保存的目的,目前redis支持两种不同方式的数据持久化保存机制,分别是RDB和AOF

2.3.2.1:RDB模式

RDB(Redis DataBase):基于时间的快照,其默认只保留当前最新的一次快照,特点是执行速度比较快,缺点是可能会丢失从上次快照到当前时间点之间未作快照的数据

RDB实现的具体过程Redis从主进程先fork出一个子进程,使用写时复制机制,子进程将内存的数据保存为一个临时文件,比如dump.rdb.temp,当数据保存完成之后再将上一次保存的RDB文件替换掉,然后关闭子进程,这样可以保证每一次做RDB快照的时候保存的数据都是完整的,因为直接替换RDB文件的时候可能会出现突然断电等问题而导致RDB文件还没有保存完整就突然关机,停止保存而导致数据丢失的情况,可以手动将每次生成的RDB文件进程备份,这样可以最大化保存历史数据

在这里插入图片描述

2.3.2.2:RDB模式的优缺点

优点:

-RDB快照保存了某个时间点的数据,可以通过脚本执行bgsave(非阻塞)命令自定义时间点备份,可以保留多个备份,当出现问题可以恢复到不同时间点的版本

可以最大化IO的性能,因为父进程再保存RDB文件的时候唯一要做的是fork出一个子进程,然后的操作都会有这个子进程操作,父进程无需任何的IO操作

RDB再大量数据比如几个G的数据,恢复的速度比AOF的快

缺点

不能时时的保存数据,会丢失自上一次RDB备份到当前的内存数据

数据量非常大的时候,从父进程fork的时侯需要一点时间,可能是毫秒或者秒或者分钟,取绝于磁盘IO性能

2.3.2.3:AOF模式:

AOF:按照操作顺序依次将操作添加到指定的日志文件中,特点是数据安全性相对较高,缺点是即使有些操作是重复的也会全部记录

AOF和RDB一样使用了写时复制机制,AOF默认为每秒钟fsync一次,即将执行的命令保存到AOF文件当中,这样即使redis服务器发生故障的话顶多也就丢失1秒钟之内的数据,也可以设置不同的fsync策略,或者设置每次执行命令的时候执行fsync,fsync会在后台执行线程,所以主线程可以继续处理用户的正常请求而不受到写入AOF文件的IO影响。

2.3.2.4:AOF模式优缺点:

AOF的文件大小要大于RDB格式的文件

根据所使用的fsync策略(fsync是同步内存中redis所有已经修改的文件到存储设备),默认是appendfsync everysec即每秒执行一次fsync

#!/bin/bash
DATE=`date +%Y-%m-%d_%H-%M-%S`
/apps/redis/bin/redis-cli -a 123456 bgsave
sleep 3
test -f /apps/redis/data/dump_6379.rdb
if [ $? -eq 0 ];then
	mv /apps/redis/data/dump_6379.rdb /data/redis/dump_6379-${DATE}.rdb
else
    sleep 30
fi

2.4:redis数据类型

http://www.redis.cn/topics/data-types-intro.html#strings

2.4.1:字符串(string):

字符串是所有编程语言中最常见和最常用的数据类型,而且也是redis最基本的数据类型之一,而且redis中所有的key的类型都是字符串

2.4.1.1:添加一个key:
127.0.0.1:6379> set name gf
OK
127.0.0.1:6379> get name
"gf"
127.0.0.1:6379> type name
string
127.0.0.1:6379> set age 18 ex 3(设置过期时间)
OK
2.4.1.2:获取一个key的内容
127.0.0.1:6379> get name
"gf"
2.4.1.3:删除一个key:
127.0.0.1:6379> del name
(integer) 1
2.4.1.4:批量设置多个key
127.0.0.1:6379> mset age 18 key1 values
OK
2.4.1.5:批量获取多个key:
127.0.0.1:6379> mget age key1
1) "18"
2) "values"
2.4.1.6:追加数据:
127.0.0.1:6379> APPEND age 22
(integer) 4
127.0.0.1:6379> get age
"1822"
2.4.1.7:数值递增:
127.0.0.1:6379> set num 10
OK
127.0.0.1:6379> INCR num
(integer) 11
127.0.0.1:6379> get num
"11"
2.4.1.8:数值递减
127.0.0.1:6379> set num 10
OK
127.0.0.1:6379> DECR num
(integer) 9
127.0.0.1:6379> get num
"9"
2.4.1.9:返回字符串key长度
127.0.0.1:6379> STRLEN age
(integer) 4
2.4.1.10:判断key是否存在
127.0.0.1:6379> EXISTS age  #存在为1
(integer) 1
127.0.0.1:6379> EXISTS kdsf
(integer) 0
2.4.1.11:查看key的过期时间:
ttl #查看key的剩余生存时间
	-1 #负一为永不过期,默认创建的key是永不过期,重新对key赋值,也会从有剩余生命周期变成永不过期
	-2 #为没有此key
	num #key的剩余有效期
127.0.0.1:6379> TTL age
(integer) -1
2.4.1.12:设置key的过期时间
127.0.0.1:6379> EXPIRE age 19
(integer) 1
2.4.1.13:取消key的过期时间
127.0.0.1:6379> set age 29 ex 22
OK
127.0.0.1:6379> ttl age
(integer) 18
127.0.0.1:6379> PERSIST age
(integer) 1
127.0.0.1:6379> ttl age
(integer) -1

2.4.2:列表(list):

列表是一个双向可读写的管道,其头部是左侧,尾部是右侧,一个列表最多可以包含2^32-1个元素即4294967295个元素

2.4.2.1:生成列表并插入数据:
127.0.0.1:6379> LPUSH student name age #根据顺序逐个写入student,最后的age会在列表的最左侧
(integer) 2
127.0.0.1:6379> TYPE student
list
2.4.2.2:向列表追加数据:
127.0.0.1:6379> LPUSH student sex
(integer) 3
127.0.0.1:6379> RPUSH student id
(integer) 4
2.4.2.3:获取列表长度:
127.0.0.1:6379> LLEN student
(integer) 4
2.4.2.4:获取列表指定位置数据:
127.0.0.1:6379> LRANGE student 1 2 #指定范围,index(下标)
1) "age"
2) "name"
2.4.2.5:移除列表数据:
127.0.0.1:6379> RPOP student #最后一个
"name"
127.0.0.1:6379> LPOP student#第一个
"sex"

2.4.3:集合(set):

set是string类型的无序集合,集合中的成员是唯一的,这就意味着集合中不能出现重复的数据,可以在两个不同的集合中对数据进行对比并取值

2.4.3.1:生成集合key:
127.0.0.1:6379> SADD set1 v1 v2 v3
(integer) 3
127.0.0.1:6379> type set1
set
2.4.3.2:追加数值:
追加的时候不能追加已经存在的数值
127.0.0.1:6379> SADD set1 v1 v3 v4
(integer) 1  #之追加了一个
2.4.3.3:查看集合的所有数据
127.0.0.1:6379> SMEMBERS set1
1) "v1"
2) "v3"
3) "v4"
4) "v2"
2.4.3.4:获取集合的差集

差集:已属于A而不属于B的元素称为A与B的差(集)

127.0.0.1:6379> SADD set2 v1 v2 v4 v5 v3
(integer) 5
127.0.0.1:6379> SADD set1 v1 v3 v4
(integer) 1
127.0.0.1:6379> SDIFF set2 set1
1) "v5"
2.4.3.5:获取集合的交集

交集:已属于A且属于B的元素称为A与B的交集(qq的共同好友)

在这里插入图片描述

127.0.0.1:6379> SINTER set1 set2
1) "v1"
2) "v3"
3) "v4"
4) "v2"
2.4.3.6:获取集合的并集:

并集:已属于A或属于B的元素称为A与B的并集

127.0.0.1:6379> SUNION set1 set2
1) "v4"
2) "v1"
3) "v5"
4) "v3"
5) "v2"

2.4.4:sorted set(有序集合)

Redis有序集合和集合一样也是string类型元素的集合,且不允许重复的成员,不同的是每个元素都会关联一个double(双精度浮点型)类型的分数,redis正是通过该分数来为集合中的成员进行从小到大的排序,有序集合的成员是唯一的,但分数(score)却可以重复,集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1),集合中最大的成员数为2^32-1(4294967295,每个集合可存储40多亿个成员)

2.4.4.1:生成有序集合
127.0.0.1:6379> ZADD zset1 1 v1
(integer) 1
127.0.0.1:6379> ZADD zset1 2 v2
(integer) 1
127.0.0.1:6379> type zset1
zset




一次生成多个数据
127.0.0.1:6379> ZADD zset2 1 v1 2 v2 3 v3 4 v4
(integer) 4
2.4.4.2:集合排序案例:
127.0.0.1:6379> ZADD paihangbang 90 nezha 199 zhanlang 60 zhuluoji
(integer) 3
127.0.0.1:6379> ZRANGE paihangbang 0 -1 #显示集合内所有的key
1) "zhuluoji"
2) "nezha"
3) "zhanlang"

127.0.0.1:6379> ZRANGE paihangbang 0 -1 withscores #显示指定集合内所有key和得分情况
1) "zhuluoji"
2) "60"
3) "nezha"
4) "90"
5) "zhanlang"
6) "199"
2.4.4.3:获取集合的长度数:
127.0.0.1:6379> ZCARD paihangbang
(integer) 3
2.4.4.4:基于索引返回数值
127.0.0.1:6379> ZRANGE paihangbang 0 2
1) "zhuluoji"
2) "nezha"
3) "zhanlang"
127.0.0.1:6379> ZRANGE paihangbang 0 -1
1) "zhuluoji"
2) "nezha"
3) "zhanlang"
2.4.4.5:返回某个数值的索引:
127.0.0.1:6379> ZRANK paihangbang nezha
(integer) 1

2.4.5:哈希(hash):

hash是一个string类型的field和value的映射表,hash特别适用于存储对象,redis中每个hash可以存储2^32-1键值对

2.4.5.1:生成hash key:
127.0.0.1:6379> HSET hash1 name tom age 12
(integer) 2
127.0.0.1:6379> TYPE hash1
hash
2.4.5.2:获取hash key字段值
127.0.0.1:6379> HGET hash1 name
"tom"
2.4.5.3:删除一个hash key的字段
127.0.0.1:6379> HDEL hash1 age
(integer) 1
2.4.5.4:获取所有hash表中的key:
127.0.0.1:6379> HSET hash1 name tom age 22 sex man
(integer) 2
127.0.0.1:6379> HKEYS hash1
1) "name"
2) "age"
3) "sex"
2.4.5.5:获取指定hash的所有key及value
127.0.0.1:6379> HGETALL hash1
1) "name"
2) "tom"
3) "age"
4) "22"
5) "sex"
6) "man"

2.5:消息队列

消息队列分为两种,分别是生产者消费者两种模式和发布者订阅者模式,这两种模式redis都支持

2.5.1:生产者消费者模式:

在生产者消费者(Producer/Consumer)模式下,上层应用接收到的外部请求后开始处理其当前步骤的操作,在执行完成后将已经完成的操作发送至指定的频道(channel)当中,并由其下层的应用监听该频道并继续下一步的操作,如果其处理完成后没有下一步就直接返回数据给外部请求,如果还有下一步的操作就在将任务发布到另外一个频道,由另外一个消费者继续监听和处理

2.5.1.1:模式介绍

生产者消费者模式下,多个消费者同时监听一个队列,但是一个消息只能被最先抢到消息的消费者消费,即消息任务是一次性读取和处理,此模式在分布式业务架构中非常常用,比较常用的软件还有RabbitMQ、Kafka、RocketMQ、ActiveMQ、zeroMQ等

在这里插入图片描述

2.5.1.2:队列介绍

队列当中的消息由不同的生产者写入也会有不同的消费者取出进行消费处理,但是一个消息一定是只能被取出一次也就是消费一次

在这里插入图片描述

2.5.1.3:生产者发布消息
127.0.0.1:6379> LPUSH channel1 msg1 #从管道的左侧写入
(integer) 1
127.0.0.1:6379> LPUSH channel1 msg2
(integer) 2
127.0.0.1:6379> LPUSH channel1 msg3
(integer) 3
2.5.1.4:查看队列所有消息
127.0.0.1:6379> LRANGE channel1 0 -1
1) "msg3"
2) "msg2"
3) "msg1"
2.5.1.5:消费者消费消息
127.0.0.1:6379> RPOP channel1
"msg1"
127.0.0.1:6379> RPOP channel1
"msg2"
127.0.0.1:6379> RPOP channel1
"msg3"
2.5.1.6:再次验证队列消息
127.0.0.1:6379> LRANGE channel1 0 -1
(empty array) #队列中的消息已经被已全部消费完毕

2.5.2:发布者订阅模式

2.5.2.1:模式简介:

在发布者订阅者模式下,发布者将消息发布到指定的channel里面,凡是监听该channel的消费者都会收到同样的一份消息,这种模式类似于是收音机的广播模式,即凡是收听某个频道的听众都会收到主持人发布的相同的内容

此模式常用语群聊天、群通知、群公告等场景
Subscriber: 订阅者
Publisher: 发布者
Channel: 频道

在这里插入图片描述

2.5.2.2:订阅者监听频道
127.0.0.1:6379> SUBSCRIBE channel1  #订阅者订阅指定的频道
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel1"
3) (integer) 1
2.5.2.3:发布者发布消息:
127.0.0.1:6379> PUBLISH channel1 test1
(integer) 1
127.0.0.1:6379> PUBLISH channel1 test2
(integer) 1
2.5.2.4:订阅多个频道
127.0.0.1:6379> SUBSCRIBE channel1 channel2 #订阅指定的多个频道
2.5.2.5:订阅所有频道
127.0.0.1:6379> PSUBSCRIBE *  
2.5.2.6:订阅匹配的频道:
127.0.0.1:6379> PSUBSCRIBE chann*

2.6:Redis常用命令

2.6.1:CONFIG:

config命令用于查看当前redis配置、以及不重启更改redis配置等

2.6.1.1:更改最大内存:
127.0.0.1:6379> config set maxmemory 1073741824
OK
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "1073741824"
2.6.1.2:设置连接密码:
127.0.0.1:6379> CONFIG set requirepass 123456
OK
/etc/redis.conf
#
requirepass 123456
2.6.1.3:获取当前配置
127.0.0.1:6379> CONFIG get *

2.6.2:显示当前redis状态

info

2.6.3:SELECT

切换数据库,等于Mysql的use DBNAME指令

127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]> SELECT 12
OK

2.6.4:keys

查看当前库下的key,不要再公司里面使用,导致redis cpu负载升高,业务中断

keys *

2.6.5:BGSAVE

手动在后台执行RDB持久化操作

127.0.0.1:6379[12]> BGSAVE
Background saving started

2.6.6:DBSIZE

返回当前库下的所有key数量

127.0.0.1:6379[1]> DBSIZE
(integer) 0

2.6.7:FLUSHDB

强制清空当前库中的所有key

2.6.8:FLUSHALL

强制清空当前redis服务器所有数据库的所有key,即删除所有数据

三:redis高可用集群

虽然redis可以实现单机的数据持久化,但无论是rdb也好或者AOF也好,都解决不了单点宕机问题,即一旦单台redis服务器本身出现系统故障、硬件故障等问题后,就会直接造成数据的丢失,因此需要使用另外的技术来解决单点问题

3.1:配置redis主从:

主备模式,可以实现Redis数据的跨主机备份

程序端连接到高可用负载的vip,然后连接到负载服务器设置的Redis后端的real server,此模式不需要在程序里面配置Redis服务器的真实IP地址,当后期Redis服务器IP地址发生变更只需要更改redis相应的后端real server即可,可避免更改程序中的IP地址即可。

在这里插入图片描述

3.1.1:Slave主要配置

Redis slave 也要开启持久化并设置和master同样的连接密码,因为后期slave会有提升为master的可能,slave端切换master同步后会丢失之前的所有数据

一旦某个Slave成为一个master的slave,Redis Slave服务会清空当前redis服务器上的所有数据并将master的数据导入到自己的内存,但是断开同步关系后不会删除当前已经同步过的数据

3.1.1.1:命令行配置

当前状态为master,需要转换为slave角色并指向master服务器的IP+PORT+PASSWORD

127.0.0.1:6379> REPLICAOF 172.16.16.100 6379
OK
127.0.0.1:6379> CONFIG set masterauth 123456
OK
3.1.1.2:同步日志

在这里插入图片描述

3.1.1.3:当前slave状态

在这里插入图片描述

3.1.1.4:保存配置到redis.conf
replicaof 172.16.10.100 6379
masterauth 123456
3.1.1.5:重启slave验证:

在这里插入图片描述

3.1.1.6:验证slave数据

在这里插入图片描述

3.1.1.7:slave状态制度无法写入数据

在这里插入图片描述

3.1.1.8:master日志

在这里插入图片描述

3.1.1.9:主从复制过程:
redis支持主从复制分为全量同步和增量同步,首次同步为全量同步,主从同步可以让从服务器从主服务器备份数据,而且从服务器还可与有从服务器,即另外一台redis服务器可以从一台从服务器进行数据同步,redis的主从同步是非阻塞的,master收到从服务器的sync(2.8版本之前是Psync)命令会fork一个子进程在后台执行bgsave命令,并将新写入的数据写入到一个缓冲区里面,bgsave执行完成之后并将生成的RDB文件法送给客户端,客户端将收到后的RDB文件载入自己的内存,然后redis master在将缓冲区的内容全部发送给redis slave,之后的同步slave服务器会发送一个offset的位置(等同于Mysql的binlog的位置)给主服务器,主服务器检查后位置没有错误将此位置之后的数据包包括写在缓冲区的积压数据发送给redis从服务器,从服务器将主服务器发送的数据导入内存,这样一次完成的数据同步。在之后在同步的时候从服务器只要发送当前的offset位置给主服务器,然后主服务器根据相应的位置将之后的数据发送给从服务器保存到其内存即可。

Redis全量复制一般发生在slave首次初始化阶段,这时slave需要将master上的所有数据都复制一份,具体主从步骤如下:

1)从服务器连接主服务器,发送SYNC命令;
2)主服务器接收到SYNC命令后,开始执行BGSAVE命令生成RDB快照文件并使用缓冲区记录此后执行的所有写命令
3)主服务器BGSAVE执行完成后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令
4)从服务器收到快照文件后丢弃所有旧数据,载入收到的快照
5)主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令
6)从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写明了
7)后期同步会先发送自己slave_repl_offset位置,只同步新增加的数据,不在全量同步

在这里插入图片描述

3.1.1.10:主从同步优化

Redis在2.8版本之前没有提供增量部分复制的功能,当网络闪断或者slave Redis重启之后会导致主从之间的全量同步,即从2.8版本开始增加了部分复制的功能

repl-diskless-sync  no #是否使用无盘同步RDB文件,默认为no,no为不适用无盘,需要RDB文件保存到磁盘后再发送给slave,yes为支持无盘,,支持无盘就是RDB文件不需要保存至本地磁盘,而且直接通过socket文件发送给slave。(根据网卡的网络带宽来设定)
repl-diskless-sync-delay 5 #master准备好RDB文件后等待传输时间

repl-ping-slave-period 10 #slave端向server端发送ping的时间区间设置,默认为10秒
repl-timeout 60 #设置超时时间

repl-disable-tcp-nodelay no #是否启用TCP_NODELAY,如设置成yes,则redis会合并小的TCP包从而节省带宽,但会增加同步延迟(40ms),造成master与slave不一致,假如设置成no,则redis master会立即发送同步数据,没有延迟,前者关注性能,后者关注redis服务中的数据一致性

repl-backlog-size 1mb #master的写入数据缓冲区,用于记录自上一次同步后到下一次同步过程中间的写入命令,计算公式:repl-backlog-size = 允许从节点最大中断时长 * 主实例offset每秒写入量,比如master每秒最大写入64mb,最大允许60秒,那么就要设置为64mb * 60秒=3840MB(3.8G)

repl-backlog-ttl 3600 #如果一段时间后没有slave连接到master,则backlog size的内存将会被释放。如果值为0则表示永远不是放这部分内存。
slave-priority 100 #slave端的优先级设置,值是一个整数,数字越小表示优先级越高,当master故障时将会按照优先级来选择slave端进行恢复,如果值设置为0,则表示该slave永远不会被选择

#min-slaves-to-wirte 1 #设置一个master端的可用slave少于多少个
#min-slaves-max-lag 20 #设置所有slave延迟时间都大于多少秒时,master不接收写操作(拒绝写入)
3.1.1.11:Slave同步过程日志:

在这里插入图片描述

3.1.1.12:master同步日志

在这里插入图片描述

3.1.1.13:slave切换master:

master的切换会导致master_replid发生变化,slave之前的master_replid就和当前master不一致从而会引发所有slave的全量同步

当前状态:

127.0.0.1:6379> info replication
# Replication
role:slave
master_host:172.16.16.100
master_port:6379
master_link_status:up
master_last_io_seconds_ago:5
master_sync_in_progress:0

停止slave同步并查看当前状态:

127.0.0.1:6379> SLAVEOF no one #提升为master,当master挂了
OK
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:ab0b13cfae3066c516d21ecea756c4f9e5edc1cc
master_replid2:c71817e443d521aa37e0114acc1a8bfe822df170
master_repl_offset:140
second_repl_offset:141
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:140

3.1.2:常见问题汇总:

3.1.2.1:master密码不对

即配置的master密码不对,导致验证不通过而无法建立主从同步关系

在这里插入图片描述

3.1.2.2:Redis版本不一致:

不同的redis版本之间存在兼容性问题,因此各master和slave之间必须保持版本一致

在这里插入图片描述

3.1.2.3:无法远程连接

再开启了安全模式情况下,没有设置bind地址或者密码

在这里插入图片描述

3.2:redis集群:

上一个步骤的主从架构无法实现master和slave角色的自动切换,即当master出现redis服务异常、主机断电、磁盘损坏等问题导致master无法使用,而redis高可用无法实现自故障转移(将slave提升为master),需要手动改环境配置才能切换到slave redis服务器,另外也无法横向扩展Redis服务的并行写入性能,当单台redis服务器性能无法满足业务.当单台Redis服务器性能无法满足业务写入需求的时候就必须需要一种方式解决以上的两个核心问题,即:1.master和slave角色的无缝切换,让业务无感知从而不影响业务使用 2.可以横向动态扩展Redis服务器,从而实现多台服务器并行写入以实现更高并发的目的。

Redis 集群实现方式: 客户端分片 代理分片 Redis Cluster

3.2.1:Sentinel(哨兵):

Sentinel进程是用于监控redis集群中master主服务器工作的状态,再master主服务器发生故障的时候,可以实现master和slave服务器的切换,保证系统的高可用,器已经被集成再redis2.6+的版本中,redis的哨兵模式到了2.8版本之后就稳定下来。一般再生产环境也建议使用redis的2.8版本的以后版本。哨兵(sentinel)是一个分布式系统,可以再一个架构中运行多个哨兵(sentinel)进程,这些进程使用流言协议(gossip protocols)来接收关于master主服务器是否下线的信息,并使用投票协议(Agreement Protocols)来决定是否执行自动故障转移,以及选择那个slave作为新的master,每个哨兵(sentinel)进程会向其他哨兵(sentinel)、Master、slave定时发送消息,以确认对方是否"活着",如果发现对方再指定配置时间(可配置的)内未得到回应,则暂时认为对方已掉线,也就是所谓的"主观认为宕机",主观是每个成员都具有的独自的而且可能相同也可能不同的意识,英文名称: Subjective Down,简称SDOWN。有主观宕机,肯定也有客观宕机。当"哨兵群"中的多数Sentinel进程在对master主服务器做出SDOWN的判断,并且通过SENTINEL is-master-down-by-addr 命令互动交流之后,得出的master slave下线判断,这种方式就是"客观宕机",客观是不依赖于某种意识而已经实际存在的一切事物,英文名称是:Objectively Down,简称ODOWN,通过一定的vote算法,从剩下的slave从服务器节点中,选一台提升为master服务器节点,然后自动修改相关配置,并开启故障转移(failover).

Sentinel 机制可以解决master和slave角色的切换问题。(读写都在一个服务器上)

在这里插入图片描述

3.2.1.1:手动配置masters

需要手动先指定某一台Redis服务器为master,然后将其他slave服务器使用命令配置为master服务器的slave,哨兵的前提是已经手动实现了一个redis master-slave的运行环境

实现一个一主两从基于哨兵的高可用redis架构

在这里插入图片描述

3.2.1.1.1:服务器A配置slave:
replicaof 172.16.16.100 6379
masterauth 123456
3.2.1.1.2:服务器B配置slave:
replicaof 172.16.16.100 6379
masterauth 123456
3.2.1.1.3:当前master状态
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.16.16.102,port=6379,state=online,offset=56,lag=1
slave1:ip=172.16.16.101,port=6379,state=online,offset=0,lag=5
master_failover_state:no-failover
master_replid:24e9f6be516150251c25cc1c2852168c24e1d2dc
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:56
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:56
3.2.1.1.4:应用程序如何连接redis?

Redis官方客户端:https://redis.io/clients

java客户端连接redis是通过Jedis来实现的,java代码用的时候只要创建Jedis对象就可以建多个Jedis连接池来连接redis,应用程序在直接调用连接池即可连接Redis

而Redis为了保障高可用,服务一般都是sentinel部署方式,当redis服务中 的主服务挂掉之后,会仲裁出另外一台slave服务充当master,这个时候,我们的应用即使使用了Jedis连接池,master服务挂了,我们的应用将还是无法连接新的master服务,为了解决这个问题,Jedis也提供了相应的Sentinel实现,能够在redis sentinel主从切换时候,通知我们的应用,吧我们的应用连接到新的master服务

Redis Sentinel的使用也是十分简单的,只是在JedisPool中添加了Sentinel和MasterName参数,Jredis Sentinel底层基于redis订阅实现redis主从服务的切换通知,当redis发生主从切换时,Sentinel会发送通知主动通知Jedis进行连接的切换,JedisSentinelPool在每次连接池中获取链接对象的时候,都要对连接对象进行检测,如果在此链接和Sentinel的master服务连接参数不一致,则会关闭此连接,重新获取新的Jedis连接对象。

3.2.1.1.5:python连接redis
import redis

pool = redis.ConnectionPool(host="172.16.16.100", port=6379,db=1,password="123456")
r = redis.Redis(connection_pool=pool)
for i in range(500):
    r.set(name="gf{}".format(i), value="gf-value{}".format(i))
3.2.1.2:编辑配置文件sentinel.conf
3.2.1.2.1: server1配置:

哨兵可以不和redis服务器部署在一起

grep "^[a-Z]" /usr/local/redis/etc/sentinel.conf
bind 0.0.0.0 
# protected-mode no
port 26379
daemonize yes
pidfile redis-sentinel.pid
logfile "sentinel_26379.log"
dir /apps/redis-sentinel
sentinel monitor mymaster 172.16.16.100 6379 2#法定人数限制(quorum),即有几个slave认为master down了就进行故障转移
sentinel auth-pass mymaster 123456
sentinel down-after-milliseconds mymaster 30000 #(SDOWN)主观下线的时间
sentinel parallel-syncs mymaster 1#发生故障转移时候同时向新master同步数据的slave数量,数字越小总同步时间越长
sentinel failover-timeout mymaster 180000#所有slave执行新的master所需的超时时间
sentinel deny-scripts-reconfig yes#禁止修改脚本
3.2.1.2.2:server2配置:
bind 0.0.0.0
# protected-mode no
port 26379
daemonize yes
pidfile redis-sentinel.pid
logfile "sentinel_26379.log"
dir /apps/redis-sentinel
sentinel monitor mymaster 172.16.16.100 6379 2
sentinel auth-pass mymaster 123456
3.2.1.2.3:server3配置
bind 0.0.0.0
# protected-mode no
port 26379
daemonize yes
pidfile redis-sentinel.pid
logfile "sentinel_26379.log"
dir /apps/redis-sentinel
sentinel monitor mymaster 172.16.16.100 6379 2
sentinel auth-pass mymaster 123456
3.2.1.3:启动哨兵

三台哨兵都要启动

redis-sentinel /apps/redis-sentinel/sentinel.conf --sentinel
3.2.1.4:验证哨兵端口

在这里插入图片描述

3.2.1.5:哨兵日志

在这里插入图片描述

3.2.1.6:当前redis master状态:
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.16.16.100,port=6379,state=online,offset=457583,lag=1
slave1:ip=172.16.16.101,port=6379,state=online,offset=0,lag=4
master_failover_state:no-failover
master_replid:dfd9216a97d7cffb2bf26acf4caaf8247c343d45
master_replid2:24e9f6be516150251c25cc1c2852168c24e1d2dc
master_repl_offset:458006
second_repl_offset:431380
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:458006
3.2.1.7:当前sentinel状态:

在sentinel状态中尤其是最后一行,涉及到masterIP是多少,有几个slave,有几个sentinels,必须是符合全部服务器数量的

[root@localhost apps]# redis-cli -h 172.16.16.103 -p 26379
127.0.0.1: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=mymaster,status=ok,address=172.16.16.102:6379,slaves=2,sentinels=3
3.2.1.8:停止redis Master测试故障转移
systemctl stop redis

故障转移日志

1379:X 20 Feb 2024 13:36:23.766 # +sdown master mymaster 172.16.16.102 6379
1379:X 20 Feb 2024 13:36:23.841 # +new-epoch 2
1379:X 20 Feb 2024 13:36:23.843 # +vote-for-leader 20c1677de6c798c1e6f0a517c9531a53715af93d 2
1379:X 20 Feb 2024 13:36:24.838 # +config-update-from sentinel 20c1677de6c798c1e6f0a517c9531a53715af93d 172.16.16.100 26379 @ mymaster 172.16.16.102 6379
1379:X 20 Feb 2024 13:36:24.838 # +switch-master mymaster 172.16.16.102 6379 172.16.16.100 6379
1379:X 20 Feb 2024 13:36:24.838 * +slave slave 172.16.16.101:6379 172.16.16.101 6379 @ mymaster 172.16.16.100 6379
1379:X 20 Feb 2024 13:36:24.838 * +slave slave 172.16.16.102:6379 172.16.16.102 6379 @ mymaster 172.16.16.100 6379
3.2.1.9:故障转移后的redis配置文件

故障转移后redis.conf中的replicaof行的master IP会被修改,sentinel.conf中的sentinel monitor IP会被修改

[root@redis2 apps]# grep "^[a-Z]" redis-sentinel/sentinel.conf 
bind 0.0.0.0
port 26379
daemonize yes
pidfile "redis-sentinel.pid"
logfile "sentinel_26379.log"
dir "/apps/redis-sentinel"
sentinel monitor mymaster 172.16.16.102 6379 2
sentinel auth-pass mymaster 123456
sentinel deny-scripts-reconfig yes
protected-mode no
user default on nopass ~* &* +@all
sentinel myid 13948a083985e2198ff1c8b46fe52fdd999c25ae
sentinel config-epoch mymaster 3
sentinel leader-epoch mymaster 3
sentinel current-epoch 3
sentinel known-replica mymaster 172.16.16.100 6379
sentinel known-replica mymaster 172.16.16.101 6379
sentinel known-sentinel mymaster 172.16.16.102 26379 e918587d879abc94d4ccaf5bbf6faa1e45d84b4f
sentinel known-sentinel mymaster 172.16.16.100 26379 20c1677de6c798c1e6f0a517c9531a53715af93d
3.2.1.10:当前redis状态

在这里插入图片描述

redis主从
	1.可以实现数据的跨主机备份
	2.但是不能实现角色自动切换,当master宕机之后需要手动将slave切换为maser
	3.不能实现性能的横向扩展
哨兵:
	1.可以实现数据的跨主机备份
	2.当master宕机之后自动将slave切换为maser
	3.不能实现性能的横向扩展

3.2.2:Redis Cluster:

早期redis分布式集群部署方案:

1) 客户端分区:有客户端程序决定key写分配和写入的redis node,但是需要客户端自己处理写入分配、高可用管理和故障转移等
2) 代理方案: 基于三方软件实现redis proxy,客户端先连接之代理层,由代理层实现key的写入分配,对客户端来说是有比较简单,但是对于集群关节点增减相对比比较麻烦,而且代理本身也是单点和性能瓶颈

在哨兵sentinel机制中,可以解决redis高可用的问题,即当master故障后可以自动将slave提升为master从而可以保证redis服务的正常使用,但是无法解决redis单机写入的瓶颈问题。即单机的redis写入性能受限于单机的内存大小、并发数量、网卡速率等因素,因此redis官方在redis3.0版本之后推出了无中心架构的redis cluster机制,再无中心的redis集群当中,其每个节点保存当前节点数据和整个集群状态,每个节点都和其他所有节点连接,特点如下

1: 所有redis节点使用(PING机制)互联
2: 集群中某个节点的失效,是整个集群中超过半数的节点检测都失效才算真正的失效
3: 客户端不需要proxy即可直接连接redis,应用程序需要写全部的redis服务器IP
4: redis cluster吧所有的redis node映射到 0-16383各槽位上(slot)上,读写需要到指定的redis node上进行操作,因此有多少个redis node相当于redis并发扩展了多少倍
5: redis cluster预先分配16384个(slot)槽位,当需要在redis集群中写入一个key -value的时候,会使用CRC16(key) mod 16384之后的值(同crc算法对key进行运算,在用16384进行取模,结果不会大于16384),决定将key的值写入哪一个槽位从而决定写入哪一个redis节点上,从而有效解决单机瓶颈
3.2.2.1:redis cluster架构
3.2.2.1.1:redis cluster基本架构:

假如三个主节点分别是:A,B,C三个节点,采用哈希槽(hash slot)的方式来分配16384个slot的话,它们三个节点分别承担的slot区间是:

节点A覆盖 0-5460
节点B覆盖 5461-10922
节点C覆盖 10923-16383

在这里插入图片描述

3.2.2.1.2:redis cluster主从架构

redis cluster的架构虽然解决了并发的问题,但是又引入了一个新的问题,每个redis master的高可用如何解决?

在这里插入图片描述

3.2.2.2:部署redis集群

环境准备:

环境A:三台服务器,每台服务器启动6379和6380两个redis服务

172.16.16.100:6379/6380
172.16.16.101:6379/6380
172.16.16.102:6379/6380

另外预留一台服务器做集群添加节点测试

172.16.16.103:6379/6380

环境B:生产环境建议直接6台服务器

172.16.16.100172.16.16.102172.16.16.105
172.16.16.101172.16.16.103172.16.16.106
预留服务器172.16.16.104172.16.16.107
3.2.2.2.1:创建redis cluster集群的前提:

1.每个redis node节点采用相同的硬件配置、相同的密码、相同的redis版本

2.每个节点必须开启的参数

cluster-enabled yes #必须开启集群状态,开启后redis进程会有cluster显示

cluster-config-file nodes-6380.conf #此文件有redis cluster集群自动创建和维护,不需要任何手动操作

3.所有redis服务器必须没有任何数据

4.先启动为单机redis且没有任何key value

在这里插入图片描述

3.2.2.2.2:创建集群

查看帮助

[root@redis1 redis]# redis-cli --cluster help
Cluster Manager Commands:
  create         host1:port1 ... hostN:portN #创建集群
                 --cluster-replicas <arg> #指定master的副本数量
  check          host:port #检查集群信息
                 --cluster-search-multiple-owners
  info           host:port #查看集群主机信息
  fix            host:port #修复集群
                 --cluster-search-multiple-owners
                 --cluster-fix-with-unreachable-masters
  reshard        host:port #在线热迁移集群指定主机的slots数据
                 --cluster-from <arg>
                 --cluster-to <arg>
                 --cluster-slots <arg>
                 --cluster-yes
                 --cluster-timeout <arg>
                 --cluster-pipeline <arg>
                 --cluster-replace
  rebalance      host:port #平衡集群中各主机的slot数量
                 --cluster-weight <node1=w1...nodeN=wN>
                 --cluster-use-empty-masters
                 --cluster-timeout <arg>
                 --cluster-simulate
                 --cluster-pipeline <arg>
                 --cluster-threshold <arg>
                 --cluster-replace
  add-node       new_host:new_port existing_host:existing_port #添加主机到集群
                 --cluster-slave
                 --cluster-master-id <arg>
  del-node       host:port node_id #删除主机
  call           host:port command arg arg .. arg #在集群上的所有节点上执行命令
                 --cluster-only-masters
                 --cluster-only-replicas
  set-timeout    host:port milliseconds #设置节点的超时时间
  import         host:port #导入外部redis服务器的数据到当前集群
                 --cluster-from <arg>
                 --cluster-from-user <arg>
                 --cluster-from-pass <arg>
                 --cluster-from-askpass
                 --cluster-copy
                 --cluster-replace
  backup         host:port backup_directory

如果有之前的操作导致redis集群创建报错,则执行情况数据和集群命令

127.0.0.1:6379> flushall
ok

127.0.0.1:6379> cluster reset
ok

初始化集群

[root@redis1 redis]# /apps/redis/bin/redis-cli -a 123456 --cluster  create 172.16.16.100:6379 172.16.16.101:6379 172.16.16.102:6379 172.16.16.103:6379 172.16.16.104:6379 172.16.16.105:6379 --cluster-replicas 1         
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.16.16.104:6379 to 172.16.16.100:6379
Adding replica 172.16.16.105:6379 to 172.16.16.101:6379
Adding replica 172.16.16.103:6379 to 172.16.16.102:6379
M: f475ca1e287d04008654254aa8183414d5e9ee7e 172.16.16.100:6379 #master的ID及端口
   slots:[0-5460] (5461 slots) master #已经分配的槽位
M: 3ec35013cce7fea2fd78fa5cb90ce16198d695ea 172.16.16.101:6379
   slots:[5461-10922] (5462 slots) master
M: 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f 172.16.16.102:6379
   slots:[10923-16383] (5461 slots) master
S: 419d5185d2a34c10834005dd679353bb3f3d9c5e 172.16.16.103:6379
   replicates 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f
S: 8e23e6a8d4e9edc38df823ed27ce20335dcd796e 172.16.16.104:6379
   replicates f475ca1e287d04008654254aa8183414d5e9ee7e
S: e5f0146048884049b3f7a41acf647bc5f4fac2b7 172.16.16.105:6379
   replicates 3ec35013cce7fea2fd78fa5cb90ce16198d695ea
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
..
>>> Performing Cluster Check (using node 172.16.16.100:6379)
M: f475ca1e287d04008654254aa8183414d5e9ee7e 172.16.16.100:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 8e23e6a8d4e9edc38df823ed27ce20335dcd796e 172.16.16.104:6379
   slots: (0 slots) slave
   replicates f475ca1e287d04008654254aa8183414d5e9ee7e
M: 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f 172.16.16.102:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 419d5185d2a34c10834005dd679353bb3f3d9c5e 172.16.16.103:6379
   slots: (0 slots) slave
   replicates 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f
S: e5f0146048884049b3f7a41acf647bc5f4fac2b7 172.16.16.105:6379
   slots: (0 slots) slave
   replicates 3ec35013cce7fea2fd78fa5cb90ce16198d695ea
M: 3ec35013cce7fea2fd78fa5cb90ce16198d695ea 172.16.16.101:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration. #所有节点槽位分配完成
>>> Check for open slots... #检查打开的槽位
>>> Check slots coverage... #检查插槽覆盖范围
[OK] All 16384 slots covered. #所有槽位分配完成
3.2.2.2.3:验证redis集群状态

查看集群信息,check

[root@redis1 ~]# redis-cli -a 123456 --cluster check 172.16.16.100:6379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
172.16.16.104:6379 (8e23e6a8...) -> 0 keys | 5461 slots | 1 slaves.
172.16.16.102:6379 (73e2ec1a...) -> 0 keys | 5461 slots | 1 slaves.
172.16.16.101:6379 (3ec35013...) -> 0 keys | 5462 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 172.16.16.100:6379)
S: f475ca1e287d04008654254aa8183414d5e9ee7e 172.16.16.100:6379
   slots: (0 slots) slave
   replicates 8e23e6a8d4e9edc38df823ed27ce20335dcd796e
M: 8e23e6a8d4e9edc38df823ed27ce20335dcd796e 172.16.16.104:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f 172.16.16.102:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 419d5185d2a34c10834005dd679353bb3f3d9c5e 172.16.16.103:6379
   slots: (0 slots) slave
   replicates 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f
S: e5f0146048884049b3f7a41acf647bc5f4fac2b7 172.16.16.105:6379
   slots: (0 slots) slave
   replicates 3ec35013cce7fea2fd78fa5cb90ce16198d695ea
M: 3ec35013cce7fea2fd78fa5cb90ce16198d695ea 172.16.16.101:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.

查看集群信息,info

[root@redis1 ~]# redis-cli -a 123456 --cluster info 172.16.16.100:6379 
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
172.16.16.104:6379 (8e23e6a8...) -> 0 keys | 5461 slots | 1 slaves.
172.16.16.102:6379 (73e2ec1a...) -> 0 keys | 5461 slots | 1 slaves.
172.16.16.101:6379 (3ec35013...) -> 0 keys | 5462 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.

非交互方式,查看集群信息

[root@redis1 ~]# redis-cli -a 123456 -h 172.16.16.100 -p 6379 cluster info
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
cluster_state:ok #集群状态,是否正常
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:7
cluster_my_epoch:7
cluster_stats_messages_ping_sent:690
cluster_stats_messages_pong_sent:744
cluster_stats_messages_sent:1434
cluster_stats_messages_ping_received:739
cluster_stats_messages_pong_received:691
cluster_stats_messages_meet_received:5
cluster_stats_messages_auth-req_received:1
cluster_stats_messages_update_received:1
cluster_stats_messages_received:1437
3.2.2.2.4:查看集群node的对应关系
127.0.0.1:6379> cluster nodes
8e23e6a8d4e9edc38df823ed27ce20335dcd796e 172.16.16.104:6379@16379 master - 0 1708488889000 7 connected 0-5460
73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f 172.16.16.102:6379@16379 master - 0 1708488888000 3 connected 10923-16383
f475ca1e287d04008654254aa8183414d5e9ee7e 172.16.16.100:6379@16379 myself,slave 8e23e6a8d4e9edc38df823ed27ce20335dcd796e 0 1708488888000 7 connected
419d5185d2a34c10834005dd679353bb3f3d9c5e 172.16.16.103:6379@16379 slave 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f 0 1708488890397 3 connected
e5f0146048884049b3f7a41acf647bc5f4fac2b7 172.16.16.105:6379@16379 slave 3ec35013cce7fea2fd78fa5cb90ce16198d695ea 0 1708488888381 2 connected
3ec35013cce7fea2fd78fa5cb90ce16198d695ea 172.16.16.101:6379@16379 master - 0 1708488889389 2 connected 5461-10922


或者查看nodes-6379.conf

redis集群中,slave是禁止读或者写数据的

python写数据

import sys
from rediscluster import RedisCluster


def conn_redis():
    startup_nodes = [
        {'host': '172.16.16.100', 'port': 6379},
        {'host': '172.16.16.101', 'port': 6379},
        {'host': '172.16.16.102', 'port': 6379},
        {'host': '172.16.16.103', 'port': 6379},
        {'host': '172.16.16.104', 'port': 6379},
        {'host': '172.16.16.105', 'port': 6379},
    ]
    try:
        conn = RedisCluster(startup_nodes=startup_nodes,decode_responses=True,password='123456')
        for i in range(100):
            conn.set("key{}".format(i),"value{}".format(i))
            data= conn.get("key{}".format(i))
            print(data)
    except Exception as e:
        print(e)
        sys.exit(1)

conn_redis()

3.2.3:Redis cluster集群节点维护

集群运行时间长久之后,难免由于硬件故障、网络规划、业务增长等原因对已有集群进行相应的调整,比如增加redis node节点、减少节点、节点迁移、更换服务器等

增加节点和删除节点会涉及到已有的槽位重新分配及数据迁移
3.2.3.1:集群维护之动态添加节点:

增加redis node节点,需要与之前的redis node版本相同、配置一致,然后分别启动两台redis node,因为一主一从

3.2.3.1.1:添加节点到集群:
add-node       new_host:new_port existing_host:existing_port
要添加的新redis节点IP和端口   添加到的集群中的master IP:端口,新的node节点加到集群之后默认是master节点,但是没有slots数据,需要重新分配
3.2.3.1.2:添加主机
[root@redis1 redis]# redis-cli -a 123456 --cluster add-node 172.16.16.106:6379 172.16.16.100:6379 #新加的默认为master,没有槽位
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Adding node 172.16.16.106:6379 to cluster 172.16.16.100:6379
>>> Performing Cluster Check (using node 172.16.16.100:6379)
S: f475ca1e287d04008654254aa8183414d5e9ee7e 172.16.16.100:6379
   slots: (0 slots) slave
   replicates 8e23e6a8d4e9edc38df823ed27ce20335dcd796e
M: 8e23e6a8d4e9edc38df823ed27ce20335dcd796e 172.16.16.104:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f 172.16.16.102:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 419d5185d2a34c10834005dd679353bb3f3d9c5e 172.16.16.103:6379
   slots: (0 slots) slave
   replicates 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f
S: e5f0146048884049b3f7a41acf647bc5f4fac2b7 172.16.16.105:6379
   slots: (0 slots) slave
   replicates 3ec35013cce7fea2fd78fa5cb90ce16198d695ea
M: 3ec35013cce7fea2fd78fa5cb90ce16198d695ea 172.16.16.101:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Send CLUSTER MEET to node 172.16.16.106:6379 to make it join the cluster.
[OK] New node added correctly.


3.2.3.1.3:分配槽位
[root@redis1 redis]# redis-cli -a 123456 --cluster reshard 172.16.16.100:6379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing Cluster Check (using node 172.16.16.100:6379)
S: f475ca1e287d04008654254aa8183414d5e9ee7e 172.16.16.100:6379
   slots: (0 slots) slave
   replicates 8e23e6a8d4e9edc38df823ed27ce20335dcd796e
M: 8e23e6a8d4e9edc38df823ed27ce20335dcd796e 172.16.16.104:6379
   slots:[1365-5460] (4096 slots) master
   1 additional replica(s)
M: 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f 172.16.16.102:6379
   slots:[12288-16383] (4096 slots) master
   1 additional replica(s)
S: 419d5185d2a34c10834005dd679353bb3f3d9c5e 172.16.16.103:6379
   slots: (0 slots) slave
   replicates 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f
S: e5f0146048884049b3f7a41acf647bc5f4fac2b7 172.16.16.105:6379
   slots: (0 slots) slave
   replicates 3ec35013cce7fea2fd78fa5cb90ce16198d695ea
M: 3ec35013cce7fea2fd78fa5cb90ce16198d695ea 172.16.16.101:6379
   slots:[6827-10922] (4096 slots) master
   1 additional replica(s)
M: 230dc2548143c3859fe10df9b99fb3e3504aeb77 172.16.16.106:6379
   slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)? 4096
What is the receiving node ID? 230dc2548143c3859fe10df9b99fb3e3504aeb77 #谁接受这些槽位
Please enter all the source node IDs.
  Type 'all' to use all the nodes as source nodes for the hash slots.
  Type 'done' once you entered all the source nodes IDs.
Source node #1: all #槽位的来源
3.2.3.1.4:为新添加的master增加slave节点
[root@redis1 redis]# redis-cli -a 123456 --cluster add-node 172.16.16.107:6379 172.16.16.100:6379 --cluster-slave --cluster-master-id 230dc2548143c3859fe10df9b99fb3e3504aeb77
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Adding node 172.16.16.107:6379 to cluster 172.16.16.100:6379
>>> Performing Cluster Check (using node 172.16.16.100:6379)
S: f475ca1e287d04008654254aa8183414d5e9ee7e 172.16.16.100:6379
   slots: (0 slots) slave
   replicates 8e23e6a8d4e9edc38df823ed27ce20335dcd796e
M: 8e23e6a8d4e9edc38df823ed27ce20335dcd796e 172.16.16.104:6379
   slots:[1365-5460] (4096 slots) master
   1 additional replica(s)
M: 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f 172.16.16.102:6379
   slots:[12288-16383] (4096 slots) master
   1 additional replica(s)
S: 419d5185d2a34c10834005dd679353bb3f3d9c5e 172.16.16.103:6379
   slots: (0 slots) slave
   replicates 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f
S: e5f0146048884049b3f7a41acf647bc5f4fac2b7 172.16.16.105:6379
   slots: (0 slots) slave
   replicates 3ec35013cce7fea2fd78fa5cb90ce16198d695ea
M: 3ec35013cce7fea2fd78fa5cb90ce16198d695ea 172.16.16.101:6379
   slots:[6827-10922] (4096 slots) master
   1 additional replica(s)
M: 230dc2548143c3859fe10df9b99fb3e3504aeb77 172.16.16.106:6379
   slots:[0-1364],[5461-6826],[10923-12287] (4096 slots) master
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Send CLUSTER MEET to node 172.16.16.107:6379 to make it join the cluster.
Waiting for the cluster to join

>>> Configure node as replica of 172.16.16.106:6379.
[OK] New node added correctly.
3.2.3.2:集群维护之动态删除节点

添加节点的时候是先添加node节点到集群,然后分配槽位,删除节点的操作与添加节点操作正好相反,是先将被删除的redis node上的槽位迁移到集群中的其他redis node节点上,然后再将其删除,如果一个redis node节点上的槽位没有被完全迁移,删除该node的时候会提示有数据无法删除

3.2.3.2.1:迁移master的槽位之其他master:

被迁移redis master源服务器必须保证没有数据,否则迁移报错并会被强制中断

迁移槽位
[root@redis1 redis]# redis-cli -a 123456 --cluster reshard 172.16.16.100:6379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing Cluster Check (using node 172.16.16.100:6379)
S: f475ca1e287d04008654254aa8183414d5e9ee7e 172.16.16.100:6379
   slots: (0 slots) slave
   replicates 8e23e6a8d4e9edc38df823ed27ce20335dcd796e
M: 8e23e6a8d4e9edc38df823ed27ce20335dcd796e 172.16.16.104:6379
   slots:[1365-5460] (4096 slots) master
   1 additional replica(s)
M: 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f 172.16.16.102:6379
   slots:[12288-16383] (4096 slots) master
   1 additional replica(s)
S: 419d5185d2a34c10834005dd679353bb3f3d9c5e 172.16.16.103:6379
   slots: (0 slots) slave
   replicates 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f
S: e5f0146048884049b3f7a41acf647bc5f4fac2b7 172.16.16.105:6379
   slots: (0 slots) slave
   replicates 3ec35013cce7fea2fd78fa5cb90ce16198d695ea
S: 7e8eac1c541ee576c462233edb86d6ae6b34780d 172.16.16.107:6379
   slots: (0 slots) slave
   replicates 3ec35013cce7fea2fd78fa5cb90ce16198d695ea
M: 3ec35013cce7fea2fd78fa5cb90ce16198d695ea 172.16.16.101:6379
   slots:[0-1364],[5461-12287] (8192 slots) master
   3 additional replica(s)
S: 230dc2548143c3859fe10df9b99fb3e3504aeb77 172.16.16.106:6379
   slots: (0 slots) slave
   replicates 3ec35013cce7fea2fd78fa5cb90ce16198d695ea
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)? 4096
What is the receiving node ID? 3ec35013cce7fea2fd78fa5cb90ce16198d695ea
Please enter all the source node IDs.
  Type 'all' to use all the nodes as source nodes for the hash slots.
  Type 'done' once you entered all the source nodes IDs.
Source node #1: 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f
Source node #2: done
移除slave
[root@redis1 redis]# redis-cli -a 123456 --cluster del-node 172.16.16.100:6379 7e8eac1c541ee576c462233edb86d6ae6b34780d
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Removing node 7e8eac1c541ee576c462233edb86d6ae6b34780d from cluster 172.16.16.100:6379
>>> Sending CLUSTER FORGET messages to the cluster...
>>> Sending CLUSTER RESET SOFT to the deleted node.
移除master
[root@redis1 redis]# redis-cli -a 123456 --cluster del-node 172.16.16.100:6379 7e8eac1c541ee576c462233edb86d6ae6b34780d
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Removing node 7e8eac1c541ee576c462233edb86d6ae6b34780d from cluster 172.16.16.100:6379
>>> Sending CLUSTER FORGET messages to the cluster...
>>> Sending CLUSTER RESET SOFT to the deleted node.
[root@redis1 redis]# redis-cli -a 123456 --cluster del-node 172.16.16.100:6379 230dc2548143c3859fe10df9b99fb3e3504aeb77
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Removing node 230dc2548143c3859fe10df9b99fb3e3504aeb77 from cluster 172.16.16.100:6379
>>> Sending CLUSTER FORGET messages to the cluster...
>>> Sending CLUSTER RESET SOFT to the deleted node.
3.2.3.3:集群维护之模拟master宕机:

目前的架构为三主三从,互为跨主机master slave模式,测试master宕机之后是否自动切换至slave

3.2.3.3.1:测试数据写入:

测试再master写入数据,并在其对应的slave验证数据

172.16.16.100:6379> set key1 value1
ok

172.16.16.100:6379> get key1
value1
3.2.3.3.2:slave验证数据
172.16.16.100:6379 172.16.16.104:6379>get key1
(error) MOVED 9189 172.16.16.100:6379 #slave不提供写,只提供数据备份即master选举

一个节点宕机,另一个节点接管,然后节点恢复,更改新节点为slave
cluster replicate masterid
3.2.3.3.3:导入node数据
[root@redis3 redis]# /apps/redis/bin/redis-cli  --cluster  import -a 123456  172.16.16.101:6379 --cluster-from 172.16.16.106:6379 --cluster-copy  --cluster-replace
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Importing data from 172.16.16.106:6379 to cluster 172.16.16.101:6379
>>> Performing Cluster Check (using node 172.16.16.101:6379)
M: 3ec35013cce7fea2fd78fa5cb90ce16198d695ea 172.16.16.101:6379
   slots:[0-1364],[5461-12287] (8192 slots) master
   1 additional replica(s)
S: f475ca1e287d04008654254aa8183414d5e9ee7e 172.16.16.100:6379
   slots: (0 slots) slave
   replicates 8e23e6a8d4e9edc38df823ed27ce20335dcd796e
S: e5f0146048884049b3f7a41acf647bc5f4fac2b7 172.16.16.105:6379
   slots: (0 slots) slave
   replicates 3ec35013cce7fea2fd78fa5cb90ce16198d695ea
M: 8e23e6a8d4e9edc38df823ed27ce20335dcd796e 172.16.16.104:6379
   slots:[1365-5460] (4096 slots) master
   1 additional replica(s)
M: 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f 172.16.16.102:6379
   slots:[12288-16383] (4096 slots) master
   1 additional replica(s)
S: 419d5185d2a34c10834005dd679353bb3f3d9c5e 172.16.16.103:6379
   slots: (0 slots) slave
   replicates 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
*** Importing 10 keys from DB 0
Migrating gf5 to 172.16.16.101:6379: OK
Migrating gf7 to 172.16.16.102:6379: OK
Migrating gf8 to 172.16.16.104:6379: OK
Migrating gf1 to 172.16.16.101:6379: OK
Migrating gf9 to 172.16.16.101:6379: OK
Migrating gf3 to 172.16.16.102:6379: OK
Migrating gf2 to 172.16.16.101:6379: OK
Migrating gf0 to 172.16.16.104:6379: OK
Migrating gf6 to 172.16.16.101:6379: OK
Migrating gf4 to 172.16.16.104:6379: OK
[root@redis3 redis]# 
3.2.3.4:数据迁移方案
1.新服务器采购及上架
2.新服务器安装操作系统及相同版本redis
3.在旧服务器导出数据
4.将新服务器加入集群
5.将槽位迁移至新服务器(必须分配源槽位,及槽位与旧服务器保持一至)
6.新服务器导入数据
7.旧服务器下线

数据导出步骤

apt install ruby rubygems ruby-dev make
gem install redis-dump
redis-dump -d 0 172.16.16.100:6379 >172.16.16.110-db0.json #导出
redis-dump -d 0 172.16.16.100:6379 <172.16.16.110-db0.json #导入

opy --cluster-replace
Warning: Using a password with ‘-a’ or ‘-u’ option on the command line interface may not be safe.

Importing data from 172.16.16.106:6379 to cluster 172.16.16.101:6379
Performing Cluster Check (using node 172.16.16.101:6379)
M: 3ec35013cce7fea2fd78fa5cb90ce16198d695ea 172.16.16.101:6379
slots:[0-1364],[5461-12287] (8192 slots) master
1 additional replica(s)
S: f475ca1e287d04008654254aa8183414d5e9ee7e 172.16.16.100:6379
slots: (0 slots) slave
replicates 8e23e6a8d4e9edc38df823ed27ce20335dcd796e
S: e5f0146048884049b3f7a41acf647bc5f4fac2b7 172.16.16.105:6379
slots: (0 slots) slave
replicates 3ec35013cce7fea2fd78fa5cb90ce16198d695ea
M: 8e23e6a8d4e9edc38df823ed27ce20335dcd796e 172.16.16.104:6379
slots:[1365-5460] (4096 slots) master
1 additional replica(s)
M: 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f 172.16.16.102:6379
slots:[12288-16383] (4096 slots) master
1 additional replica(s)
S: 419d5185d2a34c10834005dd679353bb3f3d9c5e 172.16.16.103:6379
slots: (0 slots) slave
replicates 73e2ec1a4c0bdfaf4a1195b0f003680174ff0f0f
[OK] All nodes agree about slots configuration.
Check for open slots…
Check slots coverage…
[OK] All 16384 slots covered.
*** Importing 10 keys from DB 0
Migrating gf5 to 172.16.16.101:6379: OK
Migrating gf7 to 172.16.16.102:6379: OK
Migrating gf8 to 172.16.16.104:6379: OK
Migrating gf1 to 172.16.16.101:6379: OK
Migrating gf9 to 172.16.16.101:6379: OK
Migrating gf3 to 172.16.16.102:6379: OK
Migrating gf2 to 172.16.16.101:6379: OK
Migrating gf0 to 172.16.16.104:6379: OK
Migrating gf6 to 172.16.16.101:6379: OK
Migrating gf4 to 172.16.16.104:6379: OK
[root@redis3 redis]#


#### 3.2.3.4:数据迁移方案

1.新服务器采购及上架
2.新服务器安装操作系统及相同版本redis
3.在旧服务器导出数据
4.将新服务器加入集群
5.将槽位迁移至新服务器(必须分配源槽位,及槽位与旧服务器保持一至)
6.新服务器导入数据
7.旧服务器下线


数据导出步骤

apt install ruby rubygems ruby-dev make
gem install redis-dump
redis-dump -d 0 172.16.16.100:6379 >172.16.16.110-db0.json #导出
redis-dump -d 0 172.16.16.100:6379 <172.16.16.110-db0.json #导入






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

忙里偷闲学python

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值