缓存cache 是为了调节速度不一致的两个或多个不同的物质的速度,置于中间,可以实现速度较快的一方加速访问速度较慢的一方的作用,比如CPU的一级、二级缓存是保存了CPU最近经常访问的数据,内存是保存CPU经常访问硬盘的数据,而且硬盘也有大小不一的缓存,甚至是物理服务器的raid 卡有也缓存,都是为了起到加速CPU 访问硬盘数据的目的,因为CPU的速度太快了,CPU需要的数据由于硬盘往往不能在短时间内满足CPU的需求,因此CPU缓存、内存、Raid 卡缓存以及硬盘缓存就在一定程度上满足了CPU的数据需求,即CPU 从缓存读取数据,从而可以大幅提高CPU的工作效率。
参考资料:http://www.sohu.com/a/246498483_468626
buffer:缓冲,也叫写缓冲,一般用于写操作,可以将数据先写入内存在写入磁盘,buffer 一般用于写缓冲,用于解决不同介质的速度不一致的缓冲,先将数据临时写入到里自己最近的地方,以提高写入速度,CPU会把数据先写到内存的磁盘缓冲区,然后应用就认为数据已经写入完成,然后由内核在后续的时间再写入磁盘,所以服务器突然断电会丢失内存中的部分数据。
cache:缓存,也叫读缓存,一般用于读操作,CPU读文件从内存读,如果内存没有,就先从硬盘读到内存再读到CPU,将需要频繁读取的数据放在里自己最近的缓存区域,下次读取的时候即可快速读取。
向 /proc/sys/vm/drop_caches 写入相应的修改值,会清理缓存。建议先执行sync(sync 命令将所有未写的系统缓冲区写到磁盘中,包含已修改的 i-node、已延迟的块 I/O 和读写映射文件)。执行echo 1、2、3 至 /proc/sys/vm/drop_caches, 达到不同的清理目的
如果因为是应用有像内存泄露、溢出的问题时,从swap的使用情况是可以比较快速可以判断的,但通过执行free 反而比较难查看。但核心并不会因为内存泄露等问题并没有快速清空buffer或cache(默认值是0),生产也不应该随便去改变此值。
一般情况下,应用在系统上稳定运行了,free值也会保持在一个稳定值的。当发生内存不足、应用获取不到可用内存、OOM错误等问题时,还是更应该去分析应用方面的原因,否则,清空buffer,强制腾出free的大小,可能只是把问题给暂时屏蔽了。
排除内存不足的情况外,除非是在软件开发阶段,需要临时清掉buffer,以判断应用的内存使用情况;或应用已经不再提供支持,即使应用对内存的时候确实有问题,而且无法避免的情况下,才考虑定时清空buffer。
范例:man proc
...省略... To free pagecache, use: echo 1 > /proc/sys/vm/drop_caches To free dentries and inodes, use: echo 2 > /proc/sys/vm/drop_caches To free pagecache, dentries and inodes, use: echo 3 > /proc/sys/vm/drop_caches Because writing to this file is a nondestructive operation and dirty objects are not freeable, the user should run sync(1) first.范例:清理缓存
[root@centos8 ~]#cat /proc/sys/vm/drop_caches 0 [root@centos8 ~]#free -h total used free shared buff/cache available Mem: 798Mi 198Mi 60Mi 0.0Ki 538Mi 468Mi Swap: 2.0Gi 9.0Mi 2.0Gi [root@centos8 ~]#echo 3 > /proc/sys/vm/drop_caches [root@centos8 ~]#free -h total used free shared buff/cache available Mem: 798Mi 247Mi 408Mi 1.0Mi 142Mi 426Mi Swap: 2.0Gi 9.0Mi 2.0Gi互联网应用领域,提到缓存为王
用户层: 浏览器DNS缓存,应用程序DNS缓存,操作系统DNS缓存客户端代理层: CDN,反向代理缓存Web层: 解释器Opcache,Web服务器缓存应用层: 页面静态化数据层: 分布式缓存,数据库系统层: 操作系统cache物理层: 磁盘cache, Raid Cache自动过期:给缓存的数据加上有效时间,超出时间后自动过期删除
强制过期:源网站更新图片后CDN是不会更新的,需要强制图片缓存过期 ,通过CDN管理后台实现
命中率:即缓存的读取命中率
浏览器的DNS缓存默认为60秒,即60秒之内在访问同一个域名就不再进行DNS解析 范例:查看chrome浏览器的DNS缓存 注意:此方式新版的chrome 基于安全原因不再显示缓存信息 在浏览器的地址栏上输入:chrome://net-internals/#dns
地址栏输入下面指令可以查看Firefox的缓存信息
about:cacheHTML5的新特性, 可以在html文件中进行DNS的 Prefetch
Last-Modified 是 HttpHeader 中的资源的最后修改时间,如果带有 Last-Modified ,下一次发送 Http请求时,将会发生带 If-modified-since 的 HttpHeader 。如果没有过期,将会收到 304 的响应,从缓存中读取。
浏览器请求文件时,会先获取服务器的文件的最后修改时间,再和本地浏览器缓存中的文件时间相比,如果没有发生变化就返回给浏览器304的状态码,表示没有发生变化,然后浏览器就使用的本地的缓存展示资源,如果变化,则重新再一次向服务器请求资源
此方式也需要向服务器发送请求才可以使用缓存
Etag 是 HttpHeader 中代表资源的标签,在服务器端生成。如果带有 Etag ,下一次发送带 Etag 的请求,如果 Etag 没有变化将收到 304 的响应,从缓存中读取。
基于Etag标记是否一致做判断页面是否发生过变化,比如基于Nginx 的etag on来实现。
Etag 在使用时要注意相同资源多台 Web 服务器的 Etag 的一致性 此方式也需要向服务器发送请求才可以使用缓存
以上两种都需要发送请求,即不管资源是否过期都要发送请求进行协商,这样会消耗不必要的时间,因此有了缓存的过期时间
Expire 是 HttpHeader 中代表资源的过期时间,由服务器端设置。如果带有 Expire ,则在 Expire 过期前不会发生 Http 请求,直接从缓存中读取。用户强制 F5 例外
第一次请求资源时,响应报文带有资源的过期时间,默认为30天,当前此方式使用的比较多,但是无法保证客户的时间都是准确并且一致的,因此会加入一个最大生存周期,使用用户本地的时间计算缓存数据是否超过多少天,下面的过期时间Expires:为2028年,但是缓存的最大生存周期Cache-Control: max-age=315360000,计算为天等于3650天即10年
通常 Last-Modified,Etag,Expire 是一起混合使用的
特别是 Last-Modified 和 Expire 经常一起使用,因为 Expire 可以让浏览器完全不发起 Http 请求,而当浏览器强制 F5 的时候又有 Last-Modified ,这样就很好的达到了浏览器段缓存的效果。Etag 和 Expire 一起使用时,先判断 Expire ,如果已经过期,再发起 Http 请求,如果 Etag 变化了,则返回 200 响应。如果 Etag 没有变化,则返回 304 响应。Last-Modified,Etag,Expires 三个同时使用时。先判断 Expire ,然后发送 Http 请求,服务器先判断 last-modified ,再判断 Etag ,必须都没有过期,才能返回 304 响应。缓存刷新
第一次访问,获取最新数据,返回 200响应码鼠标点击二次访问 (Cache),输入地址后回车,浏览器对所有没有过期的内容直接使用本地缓存。F5或点刷新按钮, 会向服务器发送请求缓存协商信息,last-modified和etag会有影响,但expires本地过期时间不受影响,无变化返回304按Ctrl+F5强制刷新,所有缓存不再使用,直接连接服务器,获取最新数据,返回200响应码Cookie是访问某些网站以后在本地存储的一些网站相关的信息,下次再访问的时候减少一些步骤,比如加密后的账户名密码等信息
Cookies是服务器在客户端浏览器上存储的小段文本并随每一个请求发送至同一个服务器,是一种实现客户端保持状态的方案。
session称为会话信息,位于web服务器上,主要负责访问者与网站之间的交互,当浏览器请求http地址时,可以基于之前的session实现会话保持、session共享等。
内容分发网络(Content Delivery Network,CDN)是建立并覆盖在承载网上,由不同区域的服务器组成的分布式网络。将源站资源缓存到全国各地的边缘服务器,利用全球调度系统使用户能够就近获取,有效降低访问延迟,降低源站压力,提升服务可用性。
常见的CDN服务商 百度CDN:https://cloud.baidu.com/product/cdn.html 阿里CDN:https://www.aliyun.com/product/cdn?spm=5176.8269123.416540.50.728y8n 腾讯CDN:https://www.qcloud.com/product/cdn 腾讯云CDN收费介绍:https://cloud.tencent.com/document/product/228/2949
假设您的业务源站域名为 www.test.com ,域名接入 CDN 开始使用加速服务后,当您的用户发起HTTP 请求时,实际的处理流程如下图所示: 详细说明如下:
用户向 www.test.com 下的某图片资源(如:1.jpg)发起请求,会先向 Local DNS 发起域名解析请求。当 Local DNS 解析 www.test.com 时,会发现已经配置了 CNAME www.test.com.cdn.dnsv1.com ,解析请求会发送至 Tencent DNS(GSLB),GSLB 为腾讯云自主研发的调度体系,会为请求分配最佳节点 IP。Local DNS 获取 Tencent DNS 返回的解析 IP。用户获取解析 IP。用户向获取的 IP 发起对资源 1.jpg 的访问请求。若该 IP 对应的节点缓存有 1.jpg,则会将数据直接返回给用户(10),此时请求结束。若该节点未缓存 1.jpg,则节点会向业务源站发起对 1.jpg 的请求(6、7、8),获取资源后,结合用户自定义配置的缓存策略,将资源缓存至节点(9),并返回给用户(10),此时请求结束。因为中国网络较为复杂,依赖DNS就近解析的调度,仍然会存在部分请求调度失效、调度生效慢等问题。
比如:腾讯云利用在全国部署的302重定向服务器集群,能够为每一个请求实时决策最优的服务器资源,精准解决小运营商的调度问题,提升用户访问质量, 能最快地把用户引导到最优的服务器节点上,避开性能差或者异常的节点。
提前对静态内容进行预缓存,避免大量的请求回源,导致主站网络带宽被打满而导致数据无法更新,另外CDN可以将数据根据访问的热度不同而进行不同级别的缓存,例如:访问量最高的资源访问CDN 边缘节点的内存,其次的放在SSD或者SATA,再其次的放在云存储,这样兼顾了速度与成本。
比如: 腾讯云CDN节点,根据用户的数据冷热不同,动态的进行识别,按照cache层次进行数据的存储,在访问频率到40%-90%的数据,首先放在OC边缘节点内存cache中,提供8G-64G的数据空间存储;在访问频率到30%-50%的数据,放在OC节点SSD/SATA硬盘cache中,提供1T-15T的数据空间存猪,其他的比较冷的数据,放在云存储中,采用回源拉取的方式进行处理。这样在成本和效率中计算出最优平衡点,为客户提供服务。
CDN 有效地解决了目前互联网业务中网络层面的以下问题:
用户与业务服务器地域间物理距离较远,需要进行多次网络转发,传输延时较高且不稳定。用户使用运营商与业务服务器所在运营商不同,请求需要运营商之间进行互联转发。业务服务器网络带宽、处理能力有限,当接收到海量用户请求时,会导致响应速度降低、可用性降低。利用CDN防止和抵御DDos等攻击,实现安全保护Nginx、PHP等web服务可以设置应用缓存以加速响应用户请求,另外有些解释性语言,比如:PHP/Python/Java不能直接运行,需要先编译成字节码,但字节码需要解释器解释为机器码之后才能执行,因此字节码也是一种缓存,有时候还会出现程序代码上线后字节码没有更新的现象。所以一般上线新版前,需要先将应用缓存清理,再上线新版
另外可以利用动态页面静态化技术,加速访问,比如:将访问数据库的数据的动态页面,提前用程序生成静态页面文件html.电商网站的商品介绍,评论信息非实时数据等皆可利用此技术实现
分布式缓存服务
RedisMemcached数据库
MySQL 查询缓存innodb缓存、MyISAM缓存CPU缓存(L1的数据缓存和L1的指令缓存)、二级缓存、三级缓存
数据库主要分为两大类:关系型数据库与 NoSQL 数据库。
关系型数据库,是建立在关系模型基础上的数据库,其借助于集合代数等数学概念和方法来处理数据库中的数据。主流的 MySQL、Oracle、MS SQL Server 和 DB2 都属于这类传统数据库。
NoSQL 数据库,全称为 Not Only SQL,意思就是适用关系型数据库的时候就使用关系型数据库,不适用的时候也没有必要非得使用关系型数据库不可,可以考虑使用更加合适的数据存储。主要分为临时性键值存储(memcached、Redis)、永久性键值存储(ROMA、Redis)、面向文档的数据库(MongoDB、CouchDB)、面向列的数据库(Cassandra、HBase),每种 NoSQL 都有其特有的使用场景及优点。
Oracle,mysql 等传统的关系数据库非常成熟并且已大规模商用,为什么还要用 NoSQL 数据库呢?
主要是由于随着互联网发展,数据量越来越大,对性能要求越来越高,传统数据库存在着先天性的缺陷,即单机(单库)性能瓶颈,并且扩展困难。这样既有单机单库瓶颈,却又扩展困难,自然无法满足日益增长的海量数据存储及其性能要求,所以才会出现了各种不同的 NoSQL 产品,NoSQL 根本性的优势在于在云计算时代,简单、易于大规模分布式扩展,并且读写性能非常高
RDBMS和NOSQL的特点及优缺点:
短短几年,Redis就有了很大的用户群体,目前国内外使用的公司众多,比如:阿里,百度,新浪微博,知乎网,GitHub,Twitter 等
Redis是一个开源的、遵循BSD协议的、基于内存的而且目前比较流行的键值数据库(key-value database),是一个非关系型数据库,redis 提供将内存通过网络远程共享的一种服务,提供类似功能的还有memcached,但相比memcached,redis还提供了易扩展、高性能、具备数据持久性等功能。
Redis 在高并发、低延迟环境要求比较高的环境使用量非常广泛,目前redis在DB-Engine月排行榜http s://db-engines.com/en/ranking 中一直比较靠前,而且一直是键值型存储类的首位 官网地址:https://redis.io/
Redis 6.0版本前一直是单线程方式处理用户的请求 单线程为何如此快?
纯内存非阻塞避免线程切换和竞态消耗 注意事项:一次只运行一条命令拒绝长(慢)命令:keys, flushall, flushdb, slow lua script, mutil/exec, operate big value(collection)其实不是单线程: 早期版本是单进程单线程,3版本后实际还有其它的线程, fysnc file descriptor,close file descriptor官方下载地址:http://download.redis.io/releases/
在centos系统上需要安装epel源
下载当前最新release版本 redis 源码包 网站:http://download.redis.io/releases/
官方的安装方法:
https://redis.io/download范例:编译安装过程
#安装依赖包 [root@centos8 ~]#yum -y install make gcc tcl #下载源码包 [root@centos8 ~]#wget http://download.redis.io/releases/redis-5.0.9.tar.gz [root@centos8 ~]#tar xf redis-5.0.9.tar.gz #编译安装 [root@centos8 ~]#cd redis-5.0.9/ [root@centos8 redis-5.0.9]#cd src/ [root@centos8 src]#make [root@centos8 src]#make PREFIX=/apps/redis install 配置变量 [root@centos8 src]#echo "PATH=/apps/redis/bin:$PATH" > /etc/profile.d/redis.sh [root@centos8 src]#. /etc/profile.d/redis.sh #目录结构 [root@centos8 src]#tree /apps/redis/ /apps/redis/ └── bin ├── redis-benchmark ├── redis-check-aof ├── redis-check-rdb ├── redis-cli ├── redis-sentinel -> redis-server └── redis-server 1 directory, 6 files #准备相关目录和文件 [root@centos8 ~]#mkdir /apps/redis/{etc,log,data,run} [root@centos8 ~]#cp redis-5.0.9/redis.conf /apps/redis/etc/redis-server 是redis 服务器程序
[root@centos8 ~]#redis-server --help Usage: ./redis-server [/path/to/redis.conf] [options] ./redis-server - (read config from stdin) ./redis-server -v or --version ./redis-server -h or --help ./redis-server --test-memory <megabytes> Examples: ./redis-server (run the server with default conf) ./redis-server /etc/redis/6379.conf ./redis-server --port 7777 ./redis-server --port 7777 --replicaof 127.0.0.1 8888 ./redis-server /etc/myredis.conf --loglevel verbose Sentinel mode: ./redis-server /etc/sentinel.conf --sentinel前台启动 redis
[root@centos8 ~]#redis-server /apps/redis/etc/redis.conf 16418:C 22 Oct 2020 10:43:29.813 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 16418:C 22 Oct 2020 10:43:29.813 # Redis version=5.0.9, bits=64, commit=00000000, modified=0, pid=16418, just started 16418:C 22 Oct 2020 10:43:29.813 # Configuration loaded 16418:M 22 Oct 2020 10:43:29.814 * Increased maximum number of open files to 10032 (it was originally set to 1024). _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 5.0.9 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 16418 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 16418:M 22 Oct 2020 10:43:29.815 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. 16418:M 22 Oct 2020 10:43:29.815 # Server initialized 16418:M 22 Oct 2020 10:43:29.815 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect. 16418:M 22 Oct 2020 10:43:29.815 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo madvise > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled (set to 'madvise' or 'never'). 16418:M 22 Oct 2020 10:43:29.815 * Loading RDB produced by version 6.0.8 16418:M 22 Oct 2020 10:43:29.815 * RDB age 603 seconds 16418:M 22 Oct 2020 10:43:29.815 * RDB memory usage when created 0.77 Mb 16418:M 22 Oct 2020 10:43:29.815 * DB loaded from disk: 0.000 seconds 16418:M 22 Oct 2020 10:43:29.815 * Ready to accept connections [root@centos8 ~]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 128 127.0.0.1:6379 0.0.0.0:* LISTEN 0 128 [::]:22 [::]:*范例:开启多实例
#安装依赖包 [root@centos8 ~]#yum -y install make gcc tcl #下载源码包 [root@centos8 ~]#wget http://download.redis.io/releases/redis-5.0.9.tar.gz [root@centos8 ~]#tar xf redis-5.0.9.tar.gz #编译安装 [root@centos8 ~]#cd redis-5.0.9/ [root@centos8 redis-5.0.9]#cd deps [root@centos8 deps]#make hiredis lua jemalloc linenoise [root@centos8 deps]#cd ../src [root@centos8 src]#make [root@centos8 src]#make PREFIX=/apps/redis/6379 install 配置变量 [root@centos8 src]#echo "PATH=/apps/redis/6379/bin:$PATH" > /etc/profile.d/redis.sh [root@centos8 src]#. /etc/profile.d/redis.sh #目录结构 [root@centos8 src]#tree /apps/redis/6379 /apps/redis/ └── bin ├── redis-benchmark ├── redis-check-aof ├── redis-check-rdb ├── redis-cli ├── redis-sentinel -> redis-server └── redis-server 1 directory, 6 files #准备相关目录和文件 [root@centos8 ~]#mkdir /apps/redis/6379/{etc,log,data,run} [root@centos8 ~]#cp redis-5.0.9/redis.conf /apps/redis/6379/etc/ #前台启动redis 6379 [root@centos8 redis]#redis-server --port 6379 17024:C 22 Oct 2020 11:09:08.749 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 17024:C 22 Oct 2020 11:09:08.749 # Redis version=5.0.9, bits=64, commit=00000000, modified=0, pid=17024, just started 17024:C 22 Oct 2020 11:09:08.749 # Configuration loaded 17024:M 22 Oct 2020 11:09:08.750 * Increased maximum number of open files to 10032 (it was originally set to 1024). _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 5.0.9 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 17024 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 17024:M 22 Oct 2020 11:09:08.751 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. 17024:M 22 Oct 2020 11:09:08.751 # Server initialized 17024:M 22 Oct 2020 11:09:08.751 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect. 17024:M 22 Oct 2020 11:09:08.751 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo madvise > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled (set to 'madvise' or 'never'). 17024:M 22 Oct 2020 11:09:08.751 * Ready to accept connections [root@centos8 ~]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 128 0.0.0.0:6379 0.0.0.0:* LISTEN 0 128 [::]:22 [::]:* LISTEN 0 128 [::]:6379 [::]:* [root@centos8 ~]#redis-cli -p 6379 127.0.0.1:6379> #为6380准备相关目录和文件 [root@centos8 ~]#mkdir /apps/redis/6380 [root@centos8 ~]#cp -ar /apps/redis/6379/* /apps/redis/6380/ [root@centos8 ~]#tree -d /apps/redis/ /apps/redis/ ├── 6379 │ ├── bin │ ├── data │ ├── etc │ ├── log │ └── run └── 6380 ├── bin ├── data ├── etc ├── log └── run 12 directories [root@centos8 ~]#vim /apps/redis/6380/etc/redis.conf port 6380 #前端启动6380 [root@centos8 ~]#redis-server --port 6380 17191:C 22 Oct 2020 11:17:28.354 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 17191:C 22 Oct 2020 11:17:28.354 # Redis version=5.0.9, bits=64, commit=00000000, modified=0, pid=17191, just started 17191:C 22 Oct 2020 11:17:28.354 # Configuration loaded 17191:M 22 Oct 2020 11:17:28.355 * Increased maximum number of open files to 10032 (it was originally set to 1024). _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 5.0.9 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6380 | `-._ `._ / _.-' | PID: 17191 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 17191:M 22 Oct 2020 11:17:28.355 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. 17191:M 22 Oct 2020 11:17:28.355 # Server initialized 17191:M 22 Oct 2020 11:17:28.355 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect. 17191:M 22 Oct 2020 11:17:28.355 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo madvise > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled (set to 'madvise' or 'never'). 17191:M 22 Oct 2020 11:17:28.355 * Loading RDB produced by version 6.0.8 17191:M 22 Oct 2020 11:17:28.355 * RDB age 1726 seconds 17191:M 22 Oct 2020 11:17:28.356 * RDB memory usage when created 0.77 Mb 17191:M 22 Oct 2020 11:17:28.356 * DB loaded from disk: 0.000 seconds 17191:M 22 Oct 2020 11:17:28.356 * Ready to accept connections [root@centos8 ~]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 128 0.0.0.0:6379 0.0.0.0:* LISTEN 0 128 0.0.0.0:6380 0.0.0.0:* LISTEN 0 128 [::]:22 [::]:* LISTEN 0 128 [::]:6379 [::]:* LISTEN 0 128 [::]:6380 [::]:* [root@centos8 ~]#redis-cli -p 6380 127.0.0.1:6380>警告提示如下:
17191:M 22 Oct 2020 11:17:28.355 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.backlog参数控制的是三次握手的时候server端收到client.ack确认号之后的队列值,即全连接队列
#将其值改大 [root@centos8 ~]#echo "net.core.somaxconn = 1024" >> /etc/sysctl.conf [root@centos8 ~]#sysctl -p net.core.somaxconn = 1024警告提示如下:
17191:M 22 Oct 2020 11:17:28.355 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.查看警告信息有提示,建议将其值改为1
[root@centos8 ~]#echo "vm.overcommit_memory=1" >> /etc/sysctl.conf [root@centos8 ~]#sysctl -p net.core.somaxconn = 1024 vm.overcommit_memory = 1内核参数说明:
0 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。 1 表示内核允许分配所有的物理内存,而不管当前的内存状态如何 2 表示内核允许分配超过所有物理内存和交换空间总和的内存警告提示信息如下:
17191:M 22 Oct 2020 11:17:28.355 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo madvise > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled (set to 'madvise' or 'never'). 警告:您在内核中启用了透明大页面(THP,不同于一般内存页的4k为2M)支持。 这将在Redis中造成延迟和内存使用问题。 要解决此问题,请以root 用户身份运行命令“echo never> /sys/kernel/mm/transparent_hugepage/enabled”,并将其添加到您的/etc/rc.local中,以便在重启后保留设置。禁用THP后,必须重新启动Redis。解决方法:
[root@centos8 ~]#echo never > /sys/kernel/mm/transparent_hugepage/enabled [root@centos8 ~]#echo "echo never > /sys/kernel/mm/transparent_hugepage/enabled" >> /etc/rc.d/rc.local [root@centos8 ~]#cat /etc/rc.d/rc.local #!/bin/bash # THIS FILE IS ADDED FOR COMPATIBILITY PURPOSES # # It is highly advisable to create own systemd services or udev rules # to run scripts during boot instead of using this file. # # In contrast to previous versions due to parallel execution during boot # this script will NOT be run after all other services. # # Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure # that this script will be executed during boot. touch /var/lock/subsys/local echo never > /sys/kernel/mm/transparent_hugepage/enabled [root@centos8 ~]#chmod +x /etc/rc.d/rc.local建议在其它redis服务器上做以上配置
[root@centos8 ~]#redis-server --port 6379 17436:C 22 Oct 2020 11:46:17.793 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 17436:C 22 Oct 2020 11:46:17.793 # Redis version=5.0.9, bits=64, commit=00000000, modified=0, pid=17436, just started 17436:C 22 Oct 2020 11:46:17.793 # Configuration loaded 17436:M 22 Oct 2020 11:46:17.794 * Increased maximum number of open files to 10032 (it was originally set to 1024). _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 5.0.9 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6380 | `-._ `._ / _.-' | PID: 17436 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 17436:M 22 Oct 2020 11:46:17.795 # Server initialized 17436:M 22 Oct 2020 11:46:17.795 * Loading RDB produced by version 6.0.8 17436:M 22 Oct 2020 11:46:17.795 * RDB age 3455 seconds 17436:M 22 Oct 2020 11:46:17.795 * RDB memory usage when created 0.77 Mb 17436:M 22 Oct 2020 11:46:17.795 * DB loaded from disk: 0.000 seconds 17436:M 22 Oct 2020 11:46:17.795 * Ready to accept connections格式:
redis-cli -h IP/HOSTNAME -p PORT -a PASSWORD范例:
[root@centos8 ~]#redis-cli 127.0.0.1:6379> info # Server redis_version:5.0.9 redis_git_sha1:00000000 redis_git_dirty:0 redis_build_id:aefdba51137228b0 redis_mode:standalone os:Linux 4.18.0-80.el8.x86_64 x86_64 arch_bits:64 multiplexing_api:epoll atomicvar_api:atomic-builtin gcc_version:8.2.1 process_id:11657 run_id:dbca4edaa295d162cf5de97819362e2d67cbe7b3 tcp_port:6379 uptime_in_seconds:557 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:9511796 executable:/apps/redis/bin/redis-server config_file:/apps/redis/etc/redis.conf # Clients connected_clients:1 client_recent_max_input_buffer:2 client_recent_max_output_buffer:0 blocked_clients:0 # Memory used_memory:575792 used_memory_human:562.30K used_memory_rss:5611520 used_memory_rss_human:5.35M used_memory_peak:575792 used_memory_peak_human:562.30K used_memory_peak_perc:100.18% used_memory_overhead:562590 used_memory_startup:512896 used_memory_dataset:13202 used_memory_dataset_perc:20.99% allocator_allocated:1119472 allocator_active:1449984 allocator_resident:8364032 total_system_memory:836886528 total_system_memory_human:798.12M used_memory_lua:37888 used_memory_lua_human:37.00K used_memory_scripts:0 used_memory_scripts_human:0B number_of_cached_scripts:0 maxmemory:0 maxmemory_human:0B maxmemory_policy:noeviction allocator_frag_ratio:1.30 allocator_frag_bytes:330512 allocator_rss_ratio:5.77 allocator_rss_bytes:6914048 rss_overhead_ratio:0.67 rss_overhead_bytes:-2752512 mem_fragmentation_ratio:10.51 mem_fragmentation_bytes:5077728 mem_not_counted_for_evict:0 mem_replication_backlog:0 mem_clients_slaves:0 mem_clients_normal:49694 mem_aof_buffer:0 mem_allocator:jemalloc-5.1.0 active_defrag_running:0 lazyfree_pending_objects:0 # Persistence loading:0 rdb_changes_since_last_save:0 rdb_bgsave_in_progress:0 rdb_last_save_time:1603346759 rdb_last_bgsave_status:ok rdb_last_bgsave_time_sec:-1 rdb_current_bgsave_time_sec:-1 rdb_last_cow_size:0 aof_enabled:0 aof_rewrite_in_progress:0 aof_rewrite_scheduled:0 aof_last_rewrite_time_sec:-1 aof_current_rewrite_time_sec:-1 aof_last_bgrewrite_status:ok aof_last_write_status:ok aof_last_cow_size:0 # Stats total_connections_received:1 total_commands_processed:1 instantaneous_ops_per_sec:0 total_net_input_bytes:31 total_net_output_bytes:11468 instantaneous_input_kbps:0.00 instantaneous_output_kbps:0.00 rejected_connections:0 sync_full:0 sync_partial_ok:0 sync_partial_err:0 expired_keys:0 expired_stale_perc:0.00 expired_time_cap_reached_count:0 evicted_keys:0 keyspace_hits:0 keyspace_misses:0 pubsub_channels:0 pubsub_patterns:0 latest_fork_usec:0 migrate_cached_sockets:0 slave_expires_tracked_keys:0 active_defrag_hits:0 active_defrag_misses:0 active_defrag_key_hits:0 active_defrag_key_misses:0 # Replication role:master connected_slaves:0 master_replid:931297ca953294d0e633fa5b2879be6a86db5192 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 # CPU used_cpu_sys:0.341201 used_cpu_user:0.323509 used_cpu_sys_children:0.000000 used_cpu_user_children:0.000000 # Cluster cluster_enabled:0 # Keyspace 127.0.0.1:6379>主要分为客户端连接和程序的连接
redis 支持多种开发语言访问
https://redis.io/clients范例:
[root@centos8 ~]#cat redis_test.sh #!/bin/bash NUM=100 PASS=centos for i in `seq $NUM`;do redis-cli -h 127.0.0.1 -a "$PASS" --no-auth-warning set key${i} value${i} echo "key${i} value${i} 写入完成" done echo "$NUM个key写入到Redis完成"python 多种开发库,可以支持连接redis 使用redis-py 连接 redis
官方github : https://github.com/andymccurdy/redis-py范例:
[root@centos8 ~]#yum info python3-redis Last metadata expiration check: 0:21:56 ago on Thu 22 Oct 2020 03:38:53 PM CST. Available Packages Name : python3-redis Version : 3.3.8 Release : 1.el8 Arch : noarch Size : 131 k Source : python-redis-3.3.8-1.el8.src.rpm Repo : epel Summary : Python 3 interface to the Redis key-value store URL : https://github.com/andymccurdy/redis-py License : MIT Description : This is a Python 3 interface to the Redis key-value store. [root@centos8 ~]#yum -y install python3 python3-redis #注意文件名不要为redis,会和redis模块名称冲突 [root@centos8 ~]#cat redis_test.py #!/bin/env python3 import redis #import time pool = redis.ConnectionPool(host="127.0.0.1",port=6379,password="centos") r = redis.Redis(connection_pool=pool) for i in range(100): r.set("k%d" % i,"v%d" % i) # time.sleep(1) data=r.get("k%d" % i) print(data) [root@centos8 ~]#python3 redis_test.py ...省略... b'v93' b'v94' b'v95' b'v96' b'v97' b'v98' b'v99' [root@centos8 ~]#redis-cli -a centos --no-auth-warning 127.0.0.1:6379> get k88 "v88" 127.0.0.1:6379>测试环境中经常使用多实例,需要指定不同实例的相应的端口,配置文件,日志文件等相关配置
范例:以编译安装为例实现 redis 多实例
#在前面编译安装好的基础上进行配置修改 [root@centos8 ~]#cd /apps/redis [root@centos8 redis]#mv etc/redis.conf etc/redis_6379.conf [root@centos8 redis]#vim etc/redis_6379.conf #修改以下内容 port 6379 pidfile /apps/redis/run/redis_6379.pid logfile /apps/redis/log/redis_6379.log dbfilename dump_6379.rdb appendfilename "appendonly_6379.aof" [root@centos8 redis]#mv /lib/systemd/system/redis.service /lib/systemd/system/redis_6379.service [root@centos8 redis]#vim /lib/systemd/system/redis_6379.service ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis_6379.conf --supervised systemd [root@centos8 redis]#systemctl restart redis_6379.service [root@centos8 redis]#cp -a etc/redis_6379.conf etc/redis_6380.conf [root@centos8 redis]#sed -i "s/6379/6380/g" etc/redis_6380.conf [root@centos8 redis]#cp -a /lib/systemd/system/redis_6379.service /lib/systemd/system/redis_6380.service [root@centos8 redis]#sed -i "s/6379/6380/g" /lib/systemd/system/redis_6380.service [root@centos8 redis]#systemctl enable --now redis_6380.service [root@centos8 redis]#cp -a etc/redis_6379.conf etc/redis_6381.conf [root@centos8 redis]#sed -i "s/6379/6381/g" etc/redis_6381.conf [root@centos8 redis]#cp -a /lib/systemd/system/redis_6379.service /lib/systemd/system/redis_6381.service [root@centos8 redis]#sed -i "s/6379/6381/g" /lib/systemd/system/redis_6381.service [root@centos8 redis]#systemctl daemon-reload [root@centos8 redis]#systemctl enable --now redis_6381.service #查看端口 [root@centos8 redis]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 128 0.0.0.0:6379 0.0.0.0:* LISTEN 0 128 0.0.0.0:6380 0.0.0.0:* LISTEN 0 128 0.0.0.0:6381 0.0.0.0:* LISTEN 0 128 [::]:22 [::]:* [root@centos8 ~]#tree /apps/redis/ /apps/redis/ ├── bin │ ├── redis-benchmark │ ├── redis-check-aof │ ├── redis-check-rdb │ ├── redis-cli │ ├── redis-sentinel -> redis-server │ └── redis-server ├── data │ ├── dump_6379.rdb │ ├── dump_6380.rdb │ └── dump_6381.rdb ├── etc │ ├── redis_6379.conf │ ├── redis_6380.conf │ └── redis_6381.conf ├── log │ ├── redis_6379.log │ ├── redis_6380.log │ └── redis_6381.log └── run ├── redis_6379.pid ├── redis_6380.pid └── redis_6381.pid 5 directories, 18 filesconfig 命令用于查看当前redis配置、以及不重启redis服务实现动态更改redis配置等
注意:不是所有配置都可以动态修改,且此方式无法持久保存
CONFIG SET parameter value 时间复杂度:O(1) CONFIG SET 命令可以动态地调整 Redis 服务器的配置(configuration)而无须重启。 你可以使用它修改配置参数,或者改变 Redis 的持久化(Persistence)方式。 CONFIG SET 可以修改的配置参数可以使用命令 CONFIG GET * 来列出,所有被 CONFIG SET 修改的配置参数都会立即生效。 CONFIG GET parameter 时间复杂度: O(N),其中 N 为命令返回的配置选项数量。 CONFIG GET 命令用于取得运行中的 Redis 服务器的配置参数(configuration parameters),在Redis 2.4 版本中, 有部分参数没有办法用 CONFIG GET 访问,但是在最新的 Redis 2.6 版本中,所有配置参数都已经可以用 CONFIG GET 访问了。 CONFIG GET 接受单个参数 parameter 作为搜索关键字,查找所有匹配的配置参数,其中参数和值以“键-值对”(key-value pairs)的方式排列。 比如执行 CONFIG GET s* 命令,服务器就会返回所有以 s 开头的配置参数及参数的值范例:SLOW LOG慢查询
[root@centos8 ~]#vim /etc/redis.conf #修改其慢查询的时间为1毫秒 slowlog-log-slower-than 1 #修改记录最多慢查询的长度为1024 slowlog-max-len 1024 #查看慢日志的记录条数 127.0.0.1:6379> SLOWLOG len (integer) 8 #查看慢日志的n条记录 127.0.0.1:6379> SLOWLOG get 1) 1) (integer) 8 2) (integer) 1603363724 3) (integer) 2 4) 1) "SLOWLOG" 2) "len" 5) "127.0.0.1:55098" 6) "" 2) 1) (integer) 7 2) (integer) 1603363716 3) (integer) 10 4) 1) "SLOWLOG" 2) "get" 3) "4" 5) "127.0.0.1:55098" 6) "" 3) 1) (integer) 6 2) (integer) 1603363709 3) (integer) 47 4) 1) "SLOWLOG" 2) "get" 5) "127.0.0.1:55098" 6) "" 4) 1) (integer) 5 2) (integer) 1603363705 3) (integer) 2 4) 1) "SLOWLOG" 2) "len" 5) "127.0.0.1:55098" 6) "" 5) 1) (integer) 4 2) (integer) 1603363698 3) (integer) 46 4) 1) "SLOWLOG" 2) "get" 3) "3" 5) "127.0.0.1:55098" 6) "" 6) 1) (integer) 3 2) (integer) 1603363650 3) (integer) 90 4) 1) "SLOWLOG" 2) "get" 5) "127.0.0.1:55098" 6) "" 7) 1) (integer) 2 2) (integer) 1603363645 3) (integer) 2 4) 1) "SLOWLOG" 2) "len" 5) "127.0.0.1:55098" 6) "" 8) 1) (integer) 1 2) (integer) 1603363641 3) (integer) 102 4) 1) "KEYS" 2) "*" 5) "127.0.0.1:55098" 6) "" 9) 1) (integer) 0 2) (integer) 1603363599 3) (integer) 1 4) 1) "SLOWLOG" 2) "len" 5) "127.0.0.1:55098" 6) "" 127.0.0.1:6379> SLOWLOG get 2 1) 1) (integer) 9 2) (integer) 1603363728 3) (integer) 29 4) 1) "SLOWLOG" 2) "get" 5) "127.0.0.1:55098" 6) "" 2) 1) (integer) 8 2) (integer) 1603363724 3) (integer) 2 4) 1) "SLOWLOG" 2) "len" 5) "127.0.0.1:55098" 6) "" #情况慢日志 127.0.0.1:6379> SLOWLOG reset OKRedis 虽然是一个内存级别的缓存程序,也就是redis 是使用内存进行数据的缓存的,但是其可以将内存的数据按照一定的策略保存到硬盘上,从而实现数据持久保存的目的
目前redis支持两种不同方式的数据持久化保存机制,分别是RDB和AOF
RDB(Redis DataBase):基于时间的快照,其默认只保留当前最新的一次快照,特点是执行速度比较快,缺点是可能会丢失从上次快照到当前时间点之间未做快照的数据
RDB bgsave 实现快照的具体过程: Redis从master主进程先fork出一个子进程,使用写时复制机制,子进程将内存的数据保存为一个临时文件,比如:tmp-.rdb,当数据保存完成之后再将上一次保存的RDB文件替换掉,然后关闭子进程,这样可以保证每一次做RDB快照保存的数据都是完整的
因为直接替换RDB文件的时候,可能会出现突然断电等问题,而导致RDB文件还没有保存完整就因为突然关机停止保存,而导致数据丢失的情况.后续可以手动将每次生成的RDB文件进行备份,这样可以最大化保存历史数据
范例:手动备份RDB文件的脚本
[root@centos8 ~]#vim /apps/redis/etc/redis_6379.conf save "" dbfilename dump_6379.rdb dir /apps/redis/data/ appendonly no [root@centos8 ~]#cat redis_backup_rdb.sh #!/bin/bash #*********************************************** #Author: Kingdom_Xu #Mail: 1653213432@qq.com #Version: 1.0 #Date: 2020-10-22 #FileName: redis_backup_rdb.sh #Description: The test script #Copyright (C): 2020 All rights reserved #*********************************************** . /etc/init.d/functions BACKUP=/data/redis-rdb DIR=/apps/redis FILE=dump_6379.rdb HOST=127.0.0.1 PASS=centos DATE=`date +%F_%T` redis-cli -h ${HOST} -a ${PASS} --no-auth-warning bgsave RESULT=`redis-cli -h ${HOST} -a ${PASS} --no-auth-warning info | grep "rdb_bgsave_in_progress" | sed -nr 's/.*:([0-9]+).*/\1/p'` until [ ${RESULT} -eq 0 ];do sleep 1 RESULT=`redis-cli -h ${HOST} -a ${PASS} --no-auth-warning info | grep "rdb_bgsave_in_progress" | sed -nr 's/.*:([0-9]+).*/\1/p'` done [ -d ${BACKUP} ] || mkdir -p ${BACKUP} mv ${DIR}/data/${FILE} ${BACKUP}/dump_6379-${DATE}.rdb action "Backup redis rdb successfullily" [root@centos8 ~]#bash redis_backup_rdb.sh Background saving started Backup redis rdb successfullily [ OK ] [root@centos8 ~]#ll -h /data/redis-rdb/ total 532K -rw-r--r-- 1 redis redis 529K Oct 22 20:09 dump_6379-2020-10-22_20:09:58.rdb范例: 观察save 和 bgsave的执行过程
#阻塞 #生成临时文件范例: 自动保存
[root@centos8 ~]#vim /apps/redis/etc/redis_6379.conf save 60 3 #测试60s内修改3个key,验证是否生成RDB文件 [root@centos8 ~]#cat redis_test.sh #!/bin/bash NUM=100000 PASS=centos PORT=6379 for i in `seq $NUM`;do redis-cli -h 127.0.0.1 -a "$PASS" -p $PORT --no-auth-warning set key${i} value${i} echo "key${i} value${i} 写入完成" done echo "$NUM个key写入到Redis完成" [root@centos8 ~]#bash redis_test.sh [root@centos8 ~]#ll /apps/redis/data/ total 532 -rw-r--r-- 1 redis redis 541340 Oct 22 20:16 dump_6379.rdbAOF:AppendOnylFile,按照操作顺序依次将操作追加到指定的日志文件末尾
AOF 和 RDB 一样使用了写时复制机制,AOF默认为每秒钟 fsync一次,即将执行的命令保存到AOF文件当中,这样即使redis服务器发生故障的话最多只丢失1秒钟之内的数据,也可以设置不同的fsync策略always,即设置每次执行命令的时候执行fsync,fsync会在后台执行线程,所以主线程可以继续处理用 户的正常请求而不受到写入AOF文件的I/O影响
同时启用RDB和AOF,进行恢复时,默认AOF文件优先级高于RDB文件,即会使用AOF文件进行恢复
注意: AOF 模式默认是关闭的,第一次开启AOF后,并重启服务生效后,会因为AOF的优先级高于RDB,而AOF默认没有文件存在,从而导致所有数据丢失
将一些重复的,可以合并的,过期的数据重新写入一个新的AOF文件,从而节约AOF备份占用的硬盘空间,也能加速恢复过程
可以手动执行bgrewriteaof 触发AOF,或定义自动rewrite 策略
AOF rewrite 过程 范例: 启用AOF功能的正确方式
[root@centos8 ~]#ll /var/lib/redis/ total 2032 -rw-r--r-- 1 redis redis 2077946 Oct 22 20:38 dump.rdb 127.0.0.1:6379> CONFIG GET appendonly 1) "appendonly" 2) "no" 127.0.0.1:6379> CONFIG SET appendonly yes OK [root@centos8 ~]#ll /var/lib/redis/ total 4064 -rw-r--r-- 1 redis redis 2077946 Oct 22 20:40 appendonly.aof -rw-r--r-- 1 redis redis 2077946 Oct 22 20:38 dump.rdb [root@centos8 ~]#vim /etc/redis.conf appendonly yes #config set appendonly yes 可以同时看到下面显示范例: 动态修改配置自动生成appendonly.aof文件
127.0.0.1:6379> CONFIG SET appendonly yes范例: 手动bgrewriteaof
127.0.0.1:6379> BGREWRITEAOF Background append only file rewriting started #同时可以观察到下面显示 [root@centos8 ~]#pstree -p | grep redis; ll /var/lib/redis/ |-redis-server(42039)-+-{redis-server}(42040) | |-{redis-server}(42041) | `-{redis-server}(42042) | `-sshd(12816)---sshd(12818)---bash(12819)---redis-cli(42058) total 4064 -rw-r--r-- 1 redis redis 2077946 Oct 22 21:05 appendonly.aof -rw-r--r-- 1 redis redis 2077946 Oct 22 20:46 dump.rdb如果主要充当缓存功能,或者可以承受数分钟数据的丢失, 通常生产环境一般只需启用RDB即可,此也是默认值
如果数据需要持久保存,一点不能丢失,可以选择同时开启RDB和AOF,一般不建议只开启AOF
官方文档:https://redis.io/commands 参考链接: http://redisdoc.com/
显示当前节点redis运行状态信息
127.0.0.1:6379> INFO # Server redis_version:5.0.9 redis_git_sha1:00000000 redis_git_dirty:0 redis_build_id:572b40848ddebfec redis_mode:standalone os:Linux 4.18.0-80.el8.x86_64 x86_64 arch_bits:64 multiplexing_api:epoll atomicvar_api:atomic-builtin ...省略...切换数据库,相当于在MySQL的 USE DBNAME 指令
[root@centos8 ~]#redis-cli -a centos --no-auth-warning 127.0.0.1:6379> info cluster # Cluster cluster_enabled:0 127.0.0.1:6379> SELECT 0 OK 127.0.0.1:6379> SELECT 15 OK 127.0.0.1:6379[15]> SELECT 16 (error) ERR DB index is out of range 127.0.0.1:6379[15]>注意: 在 redis cluster 模式下不支持多个数据库,会出现下面错误
[root@centos8 ~]#redis-cli 127.0.0.1:6379> info cluster # Cluster cluster_enabled:1 127.0.0.1:6379> select 0 OK 127.0.0.1:6379> select 1 (error) ERR SELECT is not allowed in cluster mode查看当前库下的所有key,此命令慎用!
127.0.0.1:6379[1]> SELECT 0 OK 127.0.0.1:6379> KEYS * #匹配数据库内所有key 1) "port1" 2) "name" 3) "port2" 4) "port" 127.0.0.1:6379> SELECT 1 OK 127.0.0.1:6379[1]> KEYS * (empty list or set) 127.0.0.1:6379[1]> 127.0.0.1:6379> SELECT 1 OK #一次设置4个key 127.0.0.1:6379[1]> MSET one 1 two 2 three 3 four 4 OK 127.0.0.1:6379[1]> KEYS *o* 1) "two" 2) "one" 3) "four"手动在后台执行RDB持久化操作
#交互式执行 127.0.0.1:6379[1]> BGSAVE Background saving started [root@centos8 ~]#ll /apps/redis/data/ total 664 -rw-r--r-- 1 redis redis 204 Oct 22 21:30 dump_6379.rdb #非交互式执行 [root@centos8 ~]#redis-cli -a centos --no-auth-warning bgsave Background saving started [root@centos8 ~]#ll /apps/redis/data/ total 664 -rw-r--r-- 1 redis redis 204 Oct 22 21:32 dump_6379.rdb返回当前库下的所有key 数量
127.0.0.1:6379> DBSIZE (integer) 8 127.0.0.1:6379> SELECT 1 OK 127.0.0.1:6379[1]> DBSIZE (integer) 4 127.0.0.1:6379[1]> SELECT 2 OK 127.0.0.1:6379[2]> DBSIZE (integer) 0强制清空当前库中的所有key,此命令慎用!
127.0.0.1:6379[2]> SELECT 1 OK 127.0.0.1:6379[1]> DBSIZE (integer) 4 127.0.0.1:6379[1]> FLUSHDB OK 127.0.0.1:6379[1]> DBSIZE (integer) 0强制清空当前redis服务器所有数据库中的所有key,即删除所有数据,此命令慎用!
127.0.0.1:6379> FLUSHALL OK #生产建议修改配置 /etc/redis.conf,禁用或改为别名 rename-command FLUSHALL ""参考资料:http://www.redis.cn/topics/data-types.html 相关命令参考: http://redisdoc.com/
字符串是所有编程语言中最常见的和最常用的数据类型,而且也是redis最基本的数据类型之一,而且redis 中所有的 key 的类型都是字符串。常用于保存 Session 信息场景,此数据类型比较常用
set 指令可以创建一个key 并赋值, 使用格式:
SET key value [EX seconds] [PX milliseconds] [NX|XX] 时间复杂度: O(1) 将字符串值 value 关联到 key 。 如果 key 已经持有其他值, SET 就覆写旧值, 无视类型。 当 SET 命令对一个带有生存时间(TTL)的键进行设置之后, 该键原有的 TTL 将被清除。 从 Redis 2.6.12 版本开始, SET 命令的行为可以通过一系列参数来修改: EX seconds : 将键的过期时间设置为 seconds 秒。 执行 SET key value EX seconds 的效果等同于执行 SETEX key seconds value 。 PX milliseconds : 将键的过期时间设置为 milliseconds 毫秒。 执行 SET key value PX milliseconds 的效果等同于执行 PSETEX key milliseconds value 。 NX : 只在键不存在时, 才对键进行设置操作。 执行 SET key value NX 的效果等同于执行 SETNX key value 。 XX : 只在键已经存在时, 才对键进行设置操作。范例:
127.0.0.1:6379> set key1 value1 OK 127.0.0.1:6379> get key1 "value1" 127.0.0.1:6379> type key1 string 127.0.0.1:6379> set title ceo ex 5 #设置自动过期时间为5秒 OK 127.0.0.1:6379> get title "ceo" 127.0.0.1:6379> get title (nil) #大小写敏感 127.0.0.1:6379> set NAME KOBE OK 127.0.0.1:6379> get NAME "KOBE" 127.0.0.1:6379> get name (nil) 127.0.0.1:6379> set name brynat OK 127.0.0.1:6379> get name "brynat" 127.0.0.1:6379> get NAME "KOBE" #key不存在才设置,相当于add 127.0.0.1:6379> get name "brynat" 127.0.0.1:6379> set name tao nx (nil) #key存在才设置,相当于update 127.0.0.1:6379> get name "brynat" 127.0.0.1:6379> set name tao xx OK 127.0.0.1:6379> get name "tao" 127.0.0.1:6379> get age (nil) 127.0.0.1:6379> set age 23 xx (nil) 127.0.0.1:6379> get age (nil)即永不过期
127.0.0.1:6379> ttl name (integer) 26 127.0.0.1:6379> PERSIST name (integer) 1 127.0.0.1:6379> ttl name (integer) -1利用INCR命令簇(INCR, DECR, [INCRBY],DECRBY)来把字符串当作原子计数器使用。
127.0.0.1:6379> set num 21 OK 127.0.0.1:6379> INCR num (integer) 22 127.0.0.1:6379> get num "22"将key对应的数字加decrement(可以是负数)。如果key不存在,操作之前,key就会被置为0。如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。这个操作最多支持64位有符号的正型数字。
127.0.0.1:6379> set num 30 OK 127.0.0.1:6379> INCRBY num 20 (integer) 50 127.0.0.1:6379> get num "50" 127.0.0.1:6379> INCRBY num -20 (integer) 30 127.0.0.1:6379> get num "30" 127.0.0.1:6379> get num1 (nil) 127.0.0.1:6379> INCRBY num1 5 (integer) 5 127.0.0.1:6379> get num1 "5"decrby 可以减小数值(也可以增加)
127.0.0.1:6379> set num 30 OK 127.0.0.1:6379> DECRBY num 20 (integer) 10 127.0.0.1:6379> get num "10" 127.0.0.1:6379> DECRBY num -20 (integer) 30 127.0.0.1:6379> get num "30" 127.0.0.1:6379> get num1 (nil) 127.0.0.1:6379> DECRBY num1 10 (integer) -10 127.0.0.1:6379> get num1 "-10"列表是一个双向可读写的管道,其头部是左侧,尾部是右侧,一个列表最多可以包含2^32-1(4294967295)个元素,下标 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。 也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,元素值可以重复,常用于存入日志等场景,此数据类型比较常用
列表特点:
有序可重复左右都可以操作LPUSH和RPUSH都可以插入列表
LPUSH key value [value …] 时间复杂度: O(1) 将一个或多个值 value 插入到列表 key 的表头 如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表头: 比如说,对空列表mylist 执行命令 LPUSH mylist a b c ,列表的值将是 c b a ,这等同于原子性地执行 LPUSH mylist a 、 LPUSH mylist b 和 LPUSH mylist c 三个命令。 如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。 当 key 存在但不是列表类型时,返回一个错误。 RPUSH key value [value …] 时间复杂度: O(1) 将一个或多个值 value 插入到列表 key 的表尾(最右边)。 如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表尾:比如对一个空列表mylist 执行 RPUSH mylist a b c ,得出的结果列表为 a b c ,等同于执行命令 RPUSH mylist a 、 RPUSH mylist b 、 RPUSH mylist c 。 如果 key 不存在,一个空列表会被创建并执行 RPUSH 操作。 当 key 存在但不是列表类型时,返回一个错误。范例:
#从左边添加数据,已添加的需向右移 127.0.0.1:6379> LPUSH name kobe bryant rose #根据顺序逐个写入name,最后的rose会在列表的最右侧 (integer) 3 127.0.0.1:6379> TYPE name list #从右边添加数据 127.0.0.1:6379> RPUSH course linux python go (integer) 3 127.0.0.1:6379> TYPE course list127.0.0.1:6379> LPUSH list1 a b c d (integer) 4 127.0.0.1:6379> LINDEX list1 0 #获取0编号的元素 "d" 127.0.0.1:6379> LINDEX list1 3 #获取3编号的元素 "a" 127.0.0.1:6379> LINDEX list1 -1 #获取最后一个的元素 "a" #元素从0开始编号 127.0.0.1:6379> LPUSH list1 a b c d (integer) 4 127.0.0.1:6379> LRANGE list1 1 2 1) "c" 2) "b" 127.0.0.1:6379> LRANGE list1 0 3 #所有元素 1) "d" 2) "c" 3) "b" 4) "a" 127.0.0.1:6379> LRANGE list1 0 -1 #所有元素 1) "d" 2) "c" 3) "b" 4) "a" 127.0.0.1:6379> RPUSH list2 zhang wang li zhao (integer) 4 127.0.0.1:6379> LRANGE list2 1 2 #指定范围 1) "wang" 2) "li" 127.0.0.1:6379> LRANGE list2 2 2 #指定位置 1) "li" 127.0.0.1:6379> LRANGE list2 0 -1 #所有元素 1) "zhang" 2) "wang" 3) "li" 4) "zhao"
Set 是 String 类型的无序集合,集合中的成员是唯一的,这就意味着集合中不能出现重复的数据,可以在两个不同的集合中对数据进行对比并取值,常用于取值判断,统计,交集等场景
集合特点:
无序无重复集合间操作集合见操作
交集:已属于A且属于B的元素称为A与B的交集
127.0.0.1:6379> SMEMBERS set1 1) "v4" 2) "v2" 3) "v5" 4) "v3" 127.0.0.1:6379> SMEMBERS set2 1) "v6" 2) "v3" 3) "v2" 127.0.0.1:6379> SINTER set1 set2 1) "v3" 2) "v2"并集:已属于A或属于B的元素称为A与B的并集
127.0.0.1:6379> SMEMBERS set1 1) "v4" 2) "v2" 3) "v5" 4) "v3" 127.0.0.1:6379> SMEMBERS set2 1) "v6" 2) "v3" 3) "v2" 127.0.0.1:6379> SUNION set1 set2 1) "v5" 2) "v4" 3) "v2" 4) "v3" 5) "v6"差集:已属于A而不属于B的元素称为A与B的差(集)
127.0.0.1:6379> SMEMBERS set1 1) "v4" 2) "v2" 3) "v5" 4) "v3" 127.0.0.1:6379> SMEMBERS set2 1) "v6" 2) "v3" 3) "v2" 127.0.0.1:6379> SDIFF set1 set2 1) "v4" 2) "v5"Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员,不同的是每个元素都会关联一个double(双精度浮点型)类型的分数,redis正是通过该分数来为集合中的成员进行从小到大的排序,有序集合的成员是唯一的,但分数(score)却可以重复,集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1), 集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员),经常用于排行榜的场景 有序集合特点:
有序无重复元素每个元素是由score和value组成score 可以重复value 不可以重复hash 是一个string类型的字段(field)和值(value)的映射表,Redis 中每个 hash 可以存储 2^32 -1 键值对,类似于字典,存放了多个k/v 对,hash特别适合用于存储对象场景
格式:
HSET hash field value 时间复杂度: O(1) 将哈希表 hash 中域 field 的值设置为 value 。 如果给定的哈希表并不存在, 那么一个新的哈希表将被创建并执行 HSET 操作。 如果域 field 已经存在于哈希表中, 那么它的旧值将被新值 value 覆盖。范例:
127.0.0.1:6379> HSET 9527 name zhouxingxing age 20 (integer) 2 127.0.0.1:6379> type 9527 hash #查看所有字段的值 127.0.0.1:6379> HGETALL 9527 1) "name" 2) "zhouxingxing" 3) "age" 4) "20" #增加字段 127.0.0.1:6379> HSET 9527 gender male (integer) 1 127.0.0.1:6379> HGETALL 9527 1) "name" 2) "zhouxingxing" 3) "age" 4) "20" 5) "gender" 6) "male"消息队列: 把要传输的数据放在队列中 功能: 可以实现多个系统之间的解耦,异步,削峰/限流等 常用的消息队列应用: kafka,rabbitMQ,redis 消息队列主要分为两种,这两种模式Redis都支持
生产者/消费者模式发布者/订阅者模式在生产者/消费者(Producer/Consumer)模式下,上层应用接收到的外部请求后开始处理其当前步骤的操作,在执行完成后将已经完成的操作发送至指定的频道(channel,逻辑队列)当中,并由其下层的应用监听该频道并继续下一步的操作,如果其处理完成后没有下一步的操作就直接返回数据给外部请求,如果还有下一步的操作就再将任务发布到另外一个频道,由另外一个消费者继续监听和处理。此模式应用广泛
生产者消费者模式下,多个消费者同时监听一个队列,但是一个消息只能被最先抢到消息的消费者消费,即消息任务是一次性读取和处理,此模式在分布式业务架构中很常用,比较常用的消息队列软件还有RabbitMQ、Kafka、RocketMQ、ActiveMQ等。
队列当中的消息由不同的生产者写入,也会有不同的消费者取出进行消费处理,但是一个消息一定是只能被取出一次也就是被消费一次。
在发布者订阅者模式下,发布者将消息发布到指定的channel里面,凡是监听该channel的消费者都会收到同样的一份消息,这种模式类似于是收音机的广播模式,即凡是收听某个频道的听众都会收到主持人发布的相同的消息内容。此模式常用于群聊天、群通知、群公告等场景
Publisher:发布者Subscriber:订阅者Channel:频道
虽然Redis可以实现单机的数据持久化,但无论是RDB也好或者AOF也好,都解决不了单点宕机问题,即一旦单台 redis服务器本身出现系统故障、硬件故障等问题后,就会直接造成数据的丢失
此外,单机的性能也是有极限的,因此需要使用另外的技术来解决单点故障和性能扩展的问题。
主从模式(master/slave),可以实现Redis数据的跨主机备份。
程序端连接到高可用负载的VIP,然后连接到负载服务器设置的Redis后端real server,此模式不需要在程序里面配置Redis服务器的真实IP地址,当后期Redis服务器IP地址发生变更只需要更改redis 相应的后端real server即可, 可避免更改程序中的IP地址设置。 主从复制特点:
一个master可以有多个slave一个slave只能有一个master数据流向是单向的,master到slaveRedis Slave 也要开启持久化并设置和master同样的连接密码,因为后期slave会有提升为master的可能,Slave 端切换master同步后会丢失之前的所有数据,而通过持久化可以恢复数据
一旦某个Slave成为一个master的slave,Redis Slave服务会清空当前redis服务器上的所有数据并将master的数据导入到自己的内存,但是如果只是断开同步关系后,则不会删除当前已经同步过的数据。
当配置Redis复制功能时,强烈建议打开主服务器的持久化功能。否则的话,由于延迟等问题,部署的服务应该要避免自动启动。
参考案例: 导致主从服务器数据全部丢失
1.假设节点A为主服务器,并且关闭了持久化。并且节点B和节点c从节点A复制数据 2.节点A崩溃,然后由自动拉起服务重启了节点A.由于节点A的持久化被关闭了,所以重启之后没有任何数据 3.节点B和节点c将从节点A复制数据,但是A的数据是空的,于是就把自身保存的数据副本删除。在关闭主服务器上的持久化,并同时开启自动拉起进程的情况下,即便使用Sentinel来实现Redis的高可用性,也是非常危险的。因为主服务器可能拉起得非常快,以至于Sentinel在配置的心跳时间间隔内没有检测到主服务器已被重启,然后还是会执行上面的数据丢失的流程。无论何时,数据安全都是极其重要的,所以应该禁止主服务器关闭持久化的同时自动启动。
默认redis 状态为master,需要转换为slave角色并指向master服务器的IP+PORT+Password
REPLICAOF MASTER_IP PORT 指令可以启用主从同步复制功能,早期版本使用 SLAVEOF 指令
127.0.0.1:6379> REPLICAOF MASTER_IP PORT 127.0.0.1:6379> CONFIG SET masterauth <masterpass> 在master上设置key1 [root@master ~]#redis-cli -a centos Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> info replication # Replication role:master connected_slaves:0 master_replid:2e389b425e8475b5e117053d91331c3e0692f64a master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 127.0.0.1:6379> set key1 v1-master OK 127.0.0.1:6379> KEYS * 1) "key1" 127.0.0.1:6379> get key1 "v1-master" #以下都在slave上执行,登录,设置key1 [root@slave1 ~]#redis-cli -a centos Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> info replication #查看当前角色默认为master # Replication role:master connected_slaves:0 master_replid:37583883b0a8c62bb8ee56d9ea720e286224f56d master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 127.0.0.1:6379> set key1 v1-slave1-18 OK 127.0.0.1:6379> keys * 1) "key1" 127.0.0.1:6379> get key1 "v1-slave1-18" #在第二个slave2上,也设置相同的key1,但值不同 [root@slave2 ~]#redis-cli -a centos Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> info replication # Replication role:master connected_slaves:0 master_replid:437af181fb73ed38b3be9995c00d23012d196de6 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 127.0.0.1:6379> set key1 v1-slave2-28 OK 127.0.0.1:6379> keys * 1) "key1" 127.0.0.1:6379> get key1 "v1-slave2-28" #在所有的slave上设置master的IP和端口,4.0版本之前的指令为slaveof 1)在slave1上 127.0.0.1:6379> replicaof 10.0.0.8 6379 #仍可使用SLAVEOF MasterIP Port OK #在slave上设置master的密码,才可以同步 127.0.0.1:6379> config set masterauth centos OK 127.0.0.1:6379> info replication # Replication role:slave #角色变为slave master_host:10.0.0.8 #指向master master_port:6379 master_link_status:up master_last_io_seconds_ago:4 master_sync_in_progress:0 slave_repl_offset:14 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:f68659a5c6e8381dbbdd6841f5b89d1a60157af8 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:14 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:14 #查看数据是否同步成功 127.0.0.1:6379> get key1 "v1-master" 2)在slave2上 127.0.0.1:6379> replicaof 10.0.0.8 6379 OK 127.0.0.1:6379> config set masterauth centos OK 127.0.0.1:6379> info replication # Replication role:slave master_host:10.0.0.8 master_port:6379 master_link_status:up master_last_io_seconds_ago:9 master_sync_in_progress:0 slave_repl_offset:560 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:f68659a5c6e8381dbbdd6841f5b89d1a60157af8 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:560 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:547 repl_backlog_histlen:14 127.0.0.1:6379> get key1 "v1-master" #在master上可以看到所有slave的信息 127.0.0.1:6379> info replication # Replication role:master connected_slaves:2 slave0:ip=10.0.0.18,port=6379,state=online,offset=672,lag=1 slave1:ip=10.0.0.28,port=6379,state=online,offset=672,lag=1 master_replid:f68659a5c6e8381dbbdd6841f5b89d1a60157af8 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:672 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:672REPLICAOF NO ONE 指令可以取消主从复制
#取消复制,在slave上执行REPLICAOF NO ONE,会断开和master的连接不再主从复制,但不会清除slave上已有的数据 1)在slave1上 127.0.0.1:6379> replicaof no one OK 127.0.0.1:6379> info replication # Replication role:master #角色变回了master connected_slaves:0 master_replid:9507932f3addde3a76b51c5d6ecbb5daac398caa master_replid2:f68659a5c6e8381dbbdd6841f5b89d1a60157af8 master_repl_offset:1064 second_repl_offset:1065 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1064 2)在master上 127.0.0.1:6379> info replication # Replication role:master connected_slaves:1 slave数量减少 slave0:ip=10.0.0.28,port=6379,state=online,offset=1260,lag=0 master_replid:f68659a5c6e8381dbbdd6841f5b89d1a60157af8 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:1260 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:1260范例:
1)在slave1上 [root@slave1 ~]#grep replicaof /etc/redis.conf # Master-Replica replication. Use replicaof to make a Redis instance a copy of # replicaof <masterip> <masterport> [root@slave1 ~]#sed -ri "s/^# (replicaof).*/\1 10.0.0.8 6379/" /etc/redis.conf [root@slave1 ~]#grep replicaof /etc/redis.conf # Master-Replica replication. Use replicaof to make a Redis instance a copy of replicaof 10.0.0.8 6379 #指定master的IP和端口号 [root@slave1 ~]#grep masterauth /etc/redis.conf # masterauth <master-password> [root@slave1 ~]#sed -ri "s/^# (masterauth).*/\1 centos/" /etc/redis.conf [root@slave1 ~]#grep masterauth /etc/redis.conf masterauth centos #设置密码 [root@slave1 ~]#systemctl restart redis 2)在slave2上 [root@slave2 ~]#grep replicaof /etc/redis.conf # Master-Replica replication. Use replicaof to make a Redis instance a copy of # replicaof <masterip> <masterport> [root@slave2 ~]#sed -ri "s/^# (replicaof).*/\1 10.0.0.8 6379/" /etc/redis.conf [root@slave2 ~]#grep replicaof /etc/redis.conf # Master-Replica replication. Use replicaof to make a Redis instance a copy of replicaof 10.0.0.8 6379 [root@slave2 ~]#grep masterauth /etc/redis.conf # masterauth <master-password> [root@slave2 ~]#sed -ri "s/^# (masterauth).*/\1 centos/" /etc/redis.conf [root@slave2 ~]#grep masterauth /etc/redis.conf masterauth centos [root@slave2 ~]#systemctl restart redisclient指向另一个从节点即可,并及时修复故障从节点
需要提升slave为新的master master故障后,只能手动提升一个slave为新master,不支持自动切换。master的切换会导致master_replid发生变化,slave之前的master_replid就和当前master不一致从而会引发所有slave的全量同步
假设当前主节点10.0.0.8故障,提升10.0.0.18为新的master
[root@master ~]#systemctl stop redis #查看当前10.0.0.18节点的状态为slave,master指向10.0.0.8 [root@slave1 ~]#redis-cli -a centos Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> info replication # Replication role:slave master_host:10.0.0.8 master_port:6379 master_link_status:down #master已宕掉 master_last_io_seconds_ago:-1 master_sync_in_progress:0 slave_repl_offset:2590 master_link_down_since_seconds:75 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:bdef83063c2c60b20a3ebc4d3794f0d8f95a4e44 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:2590 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:2590停止slave1(10.0.0.18)同步并提升为新的master
#提升为新的master 127.0.0.1:6379> replicaof no one #旧版使用SLAVEOF no one OK 127.0.0.1:6379> info replication # Replication role:master connected_slaves:0 master_replid:37b3bdf32bb1ce3442a4b2d05dcb3a1ada2af352 master_replid2:bdef83063c2c60b20a3ebc4d3794f0d8f95a4e44 master_repl_offset:2590 second_repl_offset:2591 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:2590 #测试能否写入数据: 127.0.0.1:6379> set keytest1 vtest1 OK修改所有的slave指向新的master节点
#修改10.0.0.28节点指向新的master节点10.0.0.18 127.0.0.1:6379> replicaof 10.0.0.18 6379 OK 127.0.0.1:6379> config set masterauth centos OK 127.0.0.1:6379> set key100 v100 (error) READONLY You can't write against a read only replica. 127.0.0.1:6379> info replication # Replication role:slave master_host:10.0.0.18 master_port:6379 master_link_status:up master_last_io_seconds_ago:10 master_sync_in_progress:0 slave_repl_offset:2736 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:37b3bdf32bb1ce3442a4b2d05dcb3a1ada2af352 master_replid2:bdef83063c2c60b20a3ebc4d3794f0d8f95a4e44 master_repl_offset:2736 second_repl_offset:2591 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:2736 #查看日志 7511:S 24 Oct 2020 14:25:12.275 * REPLICAOF 10.0.0.18:6379 enabled (user request from 'id=6 addr=127.0.0.1:51148 fd=7 name= age=277 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=44 qbuf-free=32724 obl=0 oll=0 omem=0 events=r cmd=replicaof') 7511:S 24 Oct 2020 14:25:12.492 * Connecting to MASTER 10.0.0.18:6379 7511:S 24 Oct 2020 14:25:12.492 * MASTER <-> REPLICA sync started 7511:S 24 Oct 2020 14:25:12.493 * Non blocking connect for SYNC fired the event. 7511:S 24 Oct 2020 14:25:12.494 * Master replied to PING, replication can continue... 7511:S 24 Oct 2020 14:25:12.497 * Trying a partial resynchronization (request 96542a696e2a90ac4197412fd2cc5a5c87d5d522:2891). 7511:S 24 Oct 2020 14:25:12.498 * Full resync from master: 37b3bdf32bb1ce3442a4b2d05dcb3a1ada2af352:2890 7511:S 24 Oct 2020 14:25:12.498 * Discarding previously cached master state. 7511:S 24 Oct 2020 14:25:12.539 * MASTER <-> REPLICA sync: receiving 214 bytes from master 7511:S 24 Oct 2020 14:25:12.539 * MASTER <-> REPLICA sync: Flushing old data 7511:S 24 Oct 2020 14:25:12.539 * MASTER <-> REPLICA sync: Loading DB in memory 7511:S 24 Oct 2020 14:25:12.539 * MASTER <-> REPLICA sync: Finished with success在新master10.0.0.18上可看到slave
127.0.0.1:6379> info replication # Replication role:master connected_slaves:1 slave0:ip=10.0.0.28,port=6379,state=online,offset=3002,lag=0 master_replid:37b3bdf32bb1ce3442a4b2d05dcb3a1ada2af352 master_replid2:bdef83063c2c60b20a3ebc4d3794f0d8f95a4e44 master_repl_offset:3002 second_repl_offset:2591 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:3002在前面搭建好的一主一从架构中,master和slave1节点无需修改,只需要修改slave2及slave3指向slave1作为master即可
#在slave2和slave3上执行下面指令 1)在slave2上 [root@slave2 ~]#redis-cli -a centos Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> replicaof 10.0.0.18 6379 OK 127.0.0.1:6379> config set masterauth centos OK 127.0.0.1:6379> INFO replication # Replication role:slave master_host:10.0.0.18 master_port:6379 master_link_status:up master_last_io_seconds_ago:1 master_sync_in_progress:0 slave_repl_offset:196 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:fcfd3bd0ac7d97d717f9a04a055f153fa8ec7715 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:196 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:196 2)在slave2上 127.0.0.1:6379> replicaof 10.0.0.18 6379 OK 127.0.0.1:6379> config set masterauth centos OK 127.0.0.1:6379> info replication # Replication role:slave master_host:10.0.0.18 master_port:6379 master_link_status:up master_last_io_seconds_ago:2 master_sync_in_progress:0 slave_repl_offset:2464 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:fcfd3bd0ac7d97d717f9a04a055f153fa8ec7715 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:2464 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:2423 repl_backlog_histlen:42在master上设置key,观察是否同步
#在master上新建key [root@master ~]#redis-cli -a centos Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> set name kobe OK 127.0.0.1:6379> get name "kobe" #在slave1,slave2和slave3上验证key 127.0.0.1:6379> get name "kobe" #在slave1和slave2以及slave3上都无法新建key 127.0.0.1:6379> set age 42 (error) READONLY You can't write against a read only replica.在中间那个slave(即级联salve1 10.0.0.18)上查看状态
127.0.0.1:6379> info replication # Replication role:slave master_host:10.0.0.8 master_port:6379 master_link_status:up master_last_io_seconds_ago:2 #最近一次与master通信已经过去多少秒 master_sync_in_progress:0 #是否正在与master通信 slave_repl_offset:3573 #当前同步的偏移量 slave_priority:100 #slave优先级,master故障后优先级值越小越优先同步 slave_read_only:1 connected_slaves:2 slave0:ip=10.0.0.28,port=6379,state=online,offset=3573,lag=0 #slave的salve节点 slave1:ip=10.0.0.38,port=6379,state=online,offset=3573,lag=0 master_replid:fcfd3bd0ac7d97d717f9a04a055f153fa8ec7715 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:3573 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:3573Redis主从复制分为全量同步和增量同步
首次同步是全量同步,主从同步可以让从服务器从主服务器同步数据,而且从服务器还可再有其它的从服务器,即另外一台redis服务器可以从一台从服务器进行数据同步,redis 的主从同步是非阻塞的,master收到从服务器的psync(2.8版本之前是SYNC)命令,会fork一个子进程在后台执行bgsave命令,并将新写入的数据写入到一个缓冲区中,bgsave执行完成之后,将生成的RDB文件发送给slave,然后master再将缓冲区的内容以redis协议格式再全部发送给slave,slave 先删除旧数据,slave将收到后的RDB文件载入自己的内存,再加载所有收到缓冲区的内容 从而这样一次完整的数据同步
Redis全量复制一般发生在Slave首次初始化阶段,这时Slave需要将Master上的所有数据都复制一份。
全量同步之后再次需要同步时,从服务器只要发送当前的offset位置(等同于MySQL的binlog的位置)给主服务器,然后主服务器根据相应的位置将之后的数据(包括写在缓冲区的积压数据)发送给从服务器,其再次保存到其内存即可。
具体主从同步过程如下:
1)从服务器连接主服务器,发送PSYNC命令 2)主服务器接收到PSYNC命令后,开始执行BGSAVE命令生成RDB快照文件并使用缓冲区记录此后执行的所有写命令 3)主服务器BGSAVE执行完后,向所有从服务器发送RDB快照文件,并在发送期间继续记录被执行的写命令 4)从服务器收到快照文件后丢弃所有旧数据,载入收到的快照至内存 5)主服务器快照发送完毕后,开始向从服务器发送缓冲区中的写命令 6)从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令 7)后期同步会先发送自己slave_repl_offset位置,只同步新增加的数据,不再全量同步复制缓冲区(环形队列)配置参数:
#复制缓冲区大小,建议要设置足够大 rep-backlog-size 1mb #Redis同时也提供了当没有slave需要同步的时候,多久可以释放环形队列: repl-backlog-ttl 3600Redis在2.8版本之前没有提供增量部分复制的功能,当网络闪断或者slave Redis重启之后会导致主从之间的全量同步,即从2.8版本开始增加了部分复制的功能。
性能相关配置
repl-diskless-sync no # 是否使用无盘同步RDB文件,默认为no,no为不使用无盘,需要将RDB文件保存到磁盘后再发送给slave,yes为支持无盘,支持无盘就是RDB文件不需要保存至本地磁盘,而且直接通过socket文件发送给slave repl-diskless-sync-delay 5 #diskless时复制的服务器等待的延迟时间 repl-ping-slave-period 10 #slave端向server端发送ping的时间间隔,默认为10秒 repl-timeout 60 #设置主从ping连接超时时间,超过此值无法连接,master_link_status显示为down,并记录错误日志 repl-disable-tcp-nodelay no #是否启用TCP_NODELAY,如设置成yes,则redis会合并小的TCP包从而节省带宽, 但会增加同步延迟(40ms),造成master与slave数据不一致,假如设置成no,则redismaster会立即发送同步数据,没有延迟,yes关注性能,no关注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-replicas-to-write 1 #设置一个master的可用slave不能少于多少个,否则master无法执行写 min-slaves-max-lag 20 #设置至少有上面数量的slave延迟时间都大于多少秒时,master不接收写操作(拒绝写入)即配置的master密码不对,导致验证不通过而无法建立主从同步关系。
[root@centos8 ~]#tail -f /var/log/redis/redis.log 3939:S 24 Oct 2020 16:13:57.552 # Server initialized 3939:S 24 Oct 2020 16:13:57.552 * DB loaded from disk: 0.000 seconds 3939:S 24 Oct 2020 16:13:57.552 * Ready to accept connections 3939:S 24 Oct 2020 16:13:57.554 * Connecting to MASTER 10.0.0.18:6379 3939:S 24 Oct 2020 16:13:57.554 * MASTER <-> REPLICA sync started 3939:S 24 Oct 2020 16:13:57.556 * Non blocking connect for SYNC fired the event. 3939:S 24 Oct 2020 16:13:57.558 * Master replied to PING, replication can continue... 3939:S 24 Oct 2020 16:13:57.559 # Unable to AUTH to MASTER: -ERR invalid password不同的redis 大版本之间存在兼容性问题,比如:3和4,4和5之间,因此各master和slave之间必须保持版本一致
在开启了安全模式情况下,没有设置bind地址或者密码
#将bind 127.0.0.1注释掉以及没有设置密码 [root@master ~]#sed -ri "s/^(bind.*)/#\1/" /etc/redis.conf [root@master ~]#systemctl restart redis [root@master ~]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 100 127.0.0.1:25 0.0.0.0:* LISTEN 0 511 0.0.0.0:6379 0.0.0.0:* LISTEN 0 128 [::]:22 [::]:* LISTEN 0 100 [::1]:25 [::]:* #在其它客户端连接10.0.0.8 [root@slave1 ~]#redis-cli -h 10.0.0.8 10.0.0.8:6379> KEYS * (error) DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode connections are only accepted from the loopback interface. If you want to connect from external computers to Redis you may adopt one of the following solutions: 1) Just disable protected mode sending the command 'CONFIG SET protected-mode no' from the loopback interface by connecting to Redis from the same host the server is running, however MAKE SURE Redis is not publicly accessible from internet if you do so. Use CONFIG REWRITE to make this change permanent. 2) Alternatively you can just disable the protected mode by editing the Redis configuration file, and setting the protected mode option to 'no', and then restarting the server. 3) If you started the server manually just for testing, restart it with the '--protected-mode no' option. 4) Setup a bind address or an authentication password. NOTE: You only need to do one of the above things in order for the server to start accepting connections from the outside. #本机登录 [root@master ~]#redis-cli 127.0.0.1:6379> KEYS * 1) "key2" 2) "name" 3) "key1"主从节点的maxmemory不一致,主节点内存大于从节点内存,主从复制可能丢失数据
rename-command 命令不一致,如在主节点定义了fushall,flushdb,从节点没定义,结果执行flushdb,不同步
#master有一个rename-command flushdb "kobe",而slave没有这个配置,则同步时从节点可以看到以下同步错误 3181:S 21 Oct 2020 17:34:50.581 # == CRITICAL == This replica is sending an error to its master: 'unknown command `kobe`, with args beginning with: ' after processing the command '<unknown>'主从架构无法实现master和slave角色的自动切换,即当master出现redis服务异常、主机断电、磁盘损坏等问题导致master无法使用,而redis主从复制无法实现自动的故障转移(将slave 自动提升为新master),需要手动修改环境配置,才能切换到slave redis服务器,另外也无法横向扩展Redis服务的并行写入性能,当单台Redis服务器性能无法满足业务写入需求的时候,也需要解决以上的两个核心问题, 即:1.master和slave角色的无缝切换,让业务无感知从而不影响业务使用 2.可横向动态扩展Redis服务器,从而实现多台服务器并行写入以实现更高并发的目的。
Redis 集群实现方式:
客户端分片: 由应用决定将不同的KEY发送到不同的Redis服务器代理分片: 由代理决定将不同的KEY发送到不同的Redis服务器,代理程序如:codis,twemproxy等Redis ClusterSentinel 进程是用于监控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 Server下线判断,这种方式就是“客观宕机”(客观:是不依赖于某种意识而已经实际存在的一切事物),英文名称是: Objectively Down, 简称 ODOWN
通过一定的vote算法,从剩下的slave从服务器节点中,选一台提升为Master服务器节点,然后自动修改相关配置,并开启故障转移(failover)
Sentinel 机制可以解决master和slave角色的自动切换问题,但单个 Master 的性能瓶颈问题无法解决,类似于MySQL中的MHA功能
Redis Sentinel中的Sentinel节点个数应该为大于等于3且最好为奇数
客户端初始化时连接的是Sentinel节点集合,不再是具体的Redis节点,但Sentinel只是配置中心不是代理。
Redis Sentinel 节点与普通redis 没有区别,要实现读写分离依赖于客户端程序
redis 3.0 之前版本中,生产环境一般使用哨兵模式,但3.0后推出redis cluster功能后,可以支持更大规模的生产环境
哨兵的前提是已经实现了一个redis的主从复制的运行环境,从而实现一个一主两从基于哨兵的高可用redis架构
注意: master 的配置文件中masterauth 和slave 都必须相同 所有主从节点的redis.conf中关健配置 范例:
#在所有主从节点执行,这里以master为例 [root@master ~]#yum -y install redis [root@master ~]#systemctl enable --now redis #交互式执行 [root@master ~]#vim /etc/redis.conf bind 0.0.0.0 masterauth "123456" requirepass "123456" #或者非交互执行,这里以master为例 [root@master ~]#sed -i -e 's/bind 127.0.0.1/bind 0.0.0.0/' -e 's/^# masterauth.*/masterauth centos/' -e 's/^# requirepass .*/requirepass centos/' /etc/redis.conf [root@master ~]#echo -e "net.core.somaxconn = 1024\nvm.overcommit_memory = 1" >> /etc/sysctl.conf [root@master ~]#sysctl -p net.core.somaxconn = 1024 vm.overcommit_memory = 1 [root@master ~]#echo never > /sys/kernel/mm/transparent_hugepage/enabled [root@master ~]#echo "echo never > /sys/kernel/mm/transparent_hugepage/enabled" >> /etc/rc.d/rc.local [root@master ~]#chmod +x /etc/rc.d/rc.local [root@master ~]#systemctl restart redis #在所有从节点执行,这里以salve1为例 [root@slave1 ~]#sed -ri "s/^# (replicaof).*/\1 10.0.0.8 6379/" /etc/redis.conf [root@slave1 ~]#systemctl restart redismaster服务器状态
[root@master ~]#redis-cli -a centos Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> info replication # Replication role:master connected_slaves:2 slave0:ip=10.0.0.18,port=6379,state=online,offset=112,lag=0 slave1:ip=10.0.0.28,port=6379,state=online,offset=112,lag=0 master_replid:4f93708e2b1ab6f3a47233db68cd99fc3db28409 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:112 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:112查看slave1和slave2
1)在slave1上 [root@slave1 ~]#redis-cli -a centos Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> info replication # Replication role:slave master_host:10.0.0.8 master_port:6379 master_link_status:up master_last_io_seconds_ago:7 master_sync_in_progress:0 slave_repl_offset:350 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:4f93708e2b1ab6f3a47233db68cd99fc3db28409 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:350 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:350 2)在slave2上 [root@slave2 ~]#redis-cli -a centos Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> info replication # Replication role:slave master_host:10.0.0.8 master_port:6379 master_link_status:up master_last_io_seconds_ago:7 master_sync_in_progress:0 slave_repl_offset:434 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:4f93708e2b1ab6f3a47233db68cd99fc3db28409 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:434 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:85 repl_backlog_histlen:350sentinel配置 Sentinel实际上是一个特殊的redis服务器,有些redis指令支持,但很多指令并不支持.默认监听在26379/tcp端口.
哨兵可以不和Redis服务器部署在一起,但一般部署在一起,所有redis节点使用相同的以下示例的配置文件
#如果是编译安装,在源码目录有sentinel.conf,复制到安装目录即可,如:/apps/redis/etc/sentinel.conf [root@master ~]#grep -Ev "^(#|$)" /etc/redis-sentinel.conf port 26379 daemonize yes pidfile /var/run/redis-sentinel.pid logfile "" dir /tmp #工作目录 sentinel monitor mymaster <MASTER_IP> 6379 2 #指定当前mymaster集群中master服务器的地址和端口 #2为法定人数限制(quorum),即有几个sentinel认为master down了就进行故障转移,一般此值是所有sentinel节点(一般总数是>=3的 奇数,如:3,5,7等)的一半以上的整数值,比如,总数是3,即3/2=1.5,取整为2,是master的ODOWN客观下线的依据 sentinel auth-pass <master-name> <password> #mymaster集群中master的密码,注意此行要在上面行的下面 sentinel down-after-milliseconds mymaster 30000 #(SDOWN)判断mymaster集群中所有节点的主观下线的时间,单位:毫秒,建议3000 sentinel parallel-syncs mymaster 1 #发生故障转移后,同时向新master同步数据的slave数量,数字越小总同步时间越长,但可以减轻新master的负载压力 sentinel failover-timeout mymaster 180000 #所有slaves指向新的master所需的超时时间,单位:毫秒 sentinel deny-scripts-reconfig yes #禁止修改脚本 logfile /var/log/redis/sentinel.log三个哨兵服务器的配置都如下,以master为例:
[root@master ~]#sed -ri -e '/^logfile ""/d' -e "s/127.0.0.1/10.0.0.8/" -e "s/^# (sentinel auth-pass) <master-name> <password>/\1 mymaster centos/" -e "s/30000/3000/" /etc/redis-sentinel.conf [root@master ~]#grep -Ev "^(#|$)" /etc/redis-sentinel.conf port 26379 daemonize no pidfile /var/run/redis-sentinel.pid dir /tmp sentinel monitor mymaster 10.0.0.8 6379 2 #修改后的内容 sentinel auth-pass mymaster centos #增加后的内容 sentinel down-after-milliseconds mymaster 3000 #修改后的内容 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 sentinel deny-scripts-reconfig yes logfile /var/log/redis/sentinel.log三台哨兵服务器都要启动
#确保每个哨兵主机myid不同 1)在master上 [root@master ~]#systemctl enable --now redis-sentinel [root@master ~]#grep myid /etc/redis-sentinel.conf sentinel myid 78af3e3a3edda463b4562c483bc5306ebdbba2fa 2)在slave1上 [root@slave1 ~]#systemctl enable --now redis-sentinel [root@slave1 ~]#grep myid /etc/redis-sentinel.conf sentinel myid 03c56cc82c32d74c473caaec5422be9ed803035c 2)在slave2上 [root@slave2 ~]#systemctl enable --now redis-sentinel [root@slave2 ~]#grep myid /etc/redis-sentinel.conf sentinel myid db9f04d90b5bc5fcb83f409592ce4273014c51dd #以下内容在服务启动后自动生成,不需要修改 [root@master ~]#grep -Ev "^(#|$)" /etc/redis-sentinel.conf ...... sentinel myid 78af3e3a3edda463b4562c483bc5306ebdbba2fa ...... protected-mode no supervised systemd sentinel leader-epoch mymaster 0 sentinel known-replica mymaster 10.0.0.28 6379 sentinel known-replica mymaster 10.0.0.18 6379 sentinel known-sentinel mymaster 10.0.0.18 26379 03c56cc82c32d74c473caaec5422be9ed803035c sentinel known-sentinel mymaster 10.0.0.28 26379 db9f04d90b5bc5fcb83f409592ce4273014c51dd如果是编译安装,在所有哨兵服务器执行下面操作启动哨兵
#vim /apps/redis/etc/sentinel.conf bind 0.0.0.0 port 26379 daemonize yes pidfile "redis-sentinel.pid" Logfile "sentinel_26379.log" dir "/apps/redis/data" sentinel monitor mymaster 10.0.0.8 6379 2 sentinel auth-pass mymaster 123456 sentinel down-after-milliseconds mymaster 15000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 sentinel deny-scripts-reconfig yes #/apps/redis/bin/redis-sentinel /apps/redis/etc/sentinel.confmaster的哨兵日志
[root@master ~]#cat /var/log/redis/sentinel.log 2074:X 24 Oct 2020 21:52:04.694 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 2074:X 24 Oct 2020 21:52:04.694 # Redis version=5.0.3, bits=64, commit=00000000, modified=0, pid=2074, just started 2074:X 24 Oct 2020 21:52:04.694 # Configuration loaded 2074:X 24 Oct 2020 21:52:04.694 * supervised by systemd, will signal readiness 2074:X 24 Oct 2020 21:52:04.697 * Running mode=sentinel, port=26379. 2074:X 24 Oct 2020 21:52:04.699 # Sentinel ID is c5325dd8405cf58245cc4febf1bbbcd6ea87e056 2074:X 24 Oct 2020 21:52:04.699 # +monitor master mymaster 10.0.0.8 6379 quorum 2 2074:X 24 Oct 2020 21:52:04.701 * +slave slave 10.0.0.18:6379 10.0.0.18 6379 @ mymaster 10.0.0.8 6379 2074:X 24 Oct 2020 21:52:04.703 * +slave slave 10.0.0.28:6379 10.0.0.28 6379 @ mymaster 10.0.0.8 6379 2074:X 24 Oct 2020 21:52:06.730 * +sentinel sentinel 56416b867d4e8dc45405261397b9b77d53bcefec 10.0.0.28 26379 @ mymaster 10.0.0.8 6379 2074:X 24 Oct 2020 21:52:06.778 * +sentinel sentinel 1fe5ef1c56e0cc263d594edae28f5321c33482b9 10.0.0.18 26379 @ mymaster 10.0.0.8 6379slave的哨兵日志
#以slave1为例 [root@slave1 ~]#cat /var/log/redis/sentinel.log 7723:X 24 Oct 2020 21:12:28.455 * Removing the pid file. 7723:X 24 Oct 2020 21:12:28.455 # Sentinel is now ready to exit, bye bye... 7814:X 24 Oct 2020 21:12:28.537 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 7814:X 24 Oct 2020 21:12:28.538 # Redis version=5.0.3, bits=64, commit=00000000, modified=0, pid=7814, just started 7814:X 24 Oct 2020 21:12:28.538 # Configuration loaded 7814:X 24 Oct 2020 21:12:28.538 * supervised by systemd, will signal readiness 7814:X 24 Oct 2020 21:12:28.539 * Running mode=sentinel, port=26379. 7814:X 24 Oct 2020 21:12:28.539 # Sentinel ID is 03c56cc82c32d74c473caaec5422be9ed803035c 7814:X 24 Oct 2020 21:12:28.539 # +monitor master mymaster 10.0.0.8 6379 quorum 2在sentinel状态中尤其是最后一行,涉及到masterIP是多少,有几个slave,有几个sentinels,必须是符合全部服务器数量
[root@master ~]#redis-cli -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=10.0.0.8:6379,slaves=2,sentinels=3 #两个slave,三个sentinel服务器,如果sentinels值不符合,检查myid可能冲突查看各节点上哨兵信息:
[root@master ~]#redis-cli -a centos -p 26379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 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=10.0.0.18:6379,slaves=2,sentinels=3故障转移时sentinel的信息:
[root@master ~]#cat /var/log/redis/sentinel.log 2490:X 24 Oct 2020 22:18:30.025 # +sdown slave 10.0.0.28:6379 10.0.0.28 6379 @ mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:18:36.154 # -sdown sentinel 56416b867d4e8dc45405261397b9b77d53bcefec 10.0.0.28 26379 @ mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:18:36.464 # -sdown slave 10.0.0.28:6379 10.0.0.28 6379 @ mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:18:59.384 # +sdown master mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:18:59.485 # +odown master mymaster 10.0.0.8 6379 #quorum 2/2 2490:X 24 Oct 2020 22:18:59.485 # +new-epoch 9 2490:X 24 Oct 2020 22:18:59.485 # +try-failover master mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:18:59.486 # +vote-for-leader c5325dd8405cf58245cc4febf1bbbcd6ea87e056 9 2490:X 24 Oct 2020 22:18:59.489 # 1fe5ef1c56e0cc263d594edae28f5321c33482b9 voted for c5325dd8405cf58245cc4febf1bbbcd6ea87e056 9 2490:X 24 Oct 2020 22:18:59.490 # 56416b867d4e8dc45405261397b9b77d53bcefec voted for c5325dd8405cf58245cc4febf1bbbcd6ea87e056 9 2490:X 24 Oct 2020 22:18:59.577 # +elected-leader master mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:18:59.577 # +failover-state-select-slave master mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:18:59.660 # +selected-slave slave 10.0.0.18:6379 10.0.0.18 6379 @ mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:18:59.660 * +failover-state-send-slaveof-noone slave 10.0.0.18:6379 10.0.0.18 6379 @ mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:18:59.718 * +failover-state-wait-promotion slave 10.0.0.18:6379 10.0.0.18 6379 @ mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:19:00.190 # +promoted-slave slave 10.0.0.18:6379 10.0.0.18 6379 @ mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:19:00.190 # +failover-state-reconf-slaves master mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:19:00.272 * +slave-reconf-sent slave 10.0.0.28:6379 10.0.0.28 6379 @ mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:19:00.608 # -odown master mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:19:00.609 * +slave-reconf-inprog slave 10.0.0.28:6379 10.0.0.28 6379 @ mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:19:01.614 * +slave-reconf-done slave 10.0.0.28:6379 10.0.0.28 6379 @ mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:19:01.665 # +failover-end master mymaster 10.0.0.8 6379 2490:X 24 Oct 2020 22:19:01.665 # +switch-master mymaster 10.0.0.8 6379 10.0.0.18 6379 2490:X 24 Oct 2020 22:19:01.666 * +slave slave 10.0.0.28:6379 10.0.0.28 6379 @ mymaster 10.0.0.18 6379 2490:X 24 Oct 2020 22:19:01.666 * +slave slave 10.0.0.8:6379 10.0.0.8 6379 @ mymaster 10.0.0.18 6379 2490:X 24 Oct 2020 22:19:04.687 # +sdown slave 10.0.0.8:6379 10.0.0.8 6379 @ mymaster 10.0.0.18 6379故障转移后其它从节点redis.conf中的replicaof行的master IP会被修改
[root@slave2 ~]#grep "^replicaof" /etc/redis.conf replicaof 10.0.0.18 6379哨兵配置文件的sentinel monitor IP 同样也会被修改
[root@master ~]#grep "^[a-Z]" /etc/redis-sentinel.conf port 26379 daemonize no pidfile "/var/run/redis-sentinel.pid" dir "/tmp" sentinel myid c5325dd8405cf58245cc4febf1bbbcd6ea87e056 sentinel deny-scripts-reconfig yes sentinel monitor mymaster 10.0.0.18 6379 2 sentinel down-after-milliseconds mymaster 3000 sentinel auth-pass mymaster centos sentinel config-epoch mymaster 9 logfile "/var/log/redis/sentinel.log" protected-mode no supervised systemd sentinel leader-epoch mymaster 9 sentinel known-replica mymaster 10.0.0.28 6379 sentinel known-replica mymaster 10.0.0.8 6379 sentinel known-sentinel mymaster 10.0.0.18 26379 1fe5ef1c56e0cc263d594edae28f5321c33482b9 sentinel known-sentinel mymaster 10.0.0.28 26379 56416b867d4e8dc45405261397b9b77d53bcefec sentinel current-epoch 9 [root@slave1 ~]#grep "^[a-Z]" /etc/redis-sentinel.conf port 26379 daemonize no pidfile "/var/run/redis-sentinel.pid" dir "/tmp" sentinel myid 1fe5ef1c56e0cc263d594edae28f5321c33482b9 sentinel deny-scripts-reconfig yes sentinel monitor mymaster 10.0.0.18 6379 2 sentinel down-after-milliseconds mymaster 3000 sentinel auth-pass mymaster centos sentinel config-epoch mymaster 9 logfile "/var/log/redis/sentinel.log" protected-mode no supervised systemd sentinel leader-epoch mymaster 9 sentinel known-replica mymaster 10.0.0.8 6379 sentinel known-replica mymaster 10.0.0.28 6379 sentinel known-sentinel mymaster 10.0.0.8 26379 c5325dd8405cf58245cc4febf1bbbcd6ea87e056 sentinel known-sentinel mymaster 10.0.0.28 26379 56416b867d4e8dc45405261397b9b77d53bcefec sentinel current-epoch 9 [root@slave2 ~]#grep "^[a-Z]" /etc/redis-sentinel.conf port 26379 daemonize no pidfile "/var/run/redis-sentinel.pid" dir "/tmp" sentinel myid 56416b867d4e8dc45405261397b9b77d53bcefec sentinel deny-scripts-reconfig yes sentinel monitor mymaster 10.0.0.18 6379 2 sentinel down-after-milliseconds mymaster 3000 sentinel auth-pass mymaster centos sentinel config-epoch mymaster 9 logfile "/var/log/redis/sentinel.log" protected-mode no supervised systemd sentinel leader-epoch mymaster 9 sentinel known-replica mymaster 10.0.0.28 6379 sentinel known-replica mymaster 10.0.0.8 6379 sentinel known-sentinel mymaster 10.0.0.18 26379 1fe5ef1c56e0cc263d594edae28f5321c33482b9 sentinel known-sentinel mymaster 10.0.0.8 26379 c5325dd8405cf58245cc4febf1bbbcd6ea87e056 sentinel current-epoch 9新的master 状态
[root@slave1 ~]#redis-cli -a centos Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> info replication # Replication role:master #提升为master connected_slaves:1 slave0:ip=10.0.0.28,port=6379,state=online,offset=162015,lag=0 master_replid:d0986944509eefec498f58c3eef54240d373ce31 master_replid2:71aa5e09a5f6c2034a5e8f853e3ec0975d9d0ff3 master_repl_offset:162015 second_repl_offset:8732 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:162015另一个slave指向新的master
[root@slave2 ~]#redis-cli -a centos Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> info replication # Replication role:slave master_host:10.0.0.18 #指向新的master master_port:6379 master_link_status:up master_last_io_seconds_ago:1 master_sync_in_progress:0 slave_repl_offset:196879 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:d0986944509eefec498f58c3eef54240d373ce31 master_replid2:71aa5e09a5f6c2034a5e8f853e3ec0975d9d0ff3 master_repl_offset:196879 second_repl_offset:8732 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:6851 repl_backlog_histlen:190029在原 master上观察状态
[root@master ~]#redis-cli -a centos Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> info replication # Replication role:slave master_host:10.0.0.18 master_port:6379 master_link_status:up master_last_io_seconds_ago:1 master_sync_in_progress:0 slave_repl_offset:241800 slave_priority:100 slave_read_only:1 connected_slaves:0 master_replid:d0986944509eefec498f58c3eef54240d373ce31 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:241800 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:216787 repl_backlog_histlen:25014 [root@master ~]#redis-cli -a centos -p 26379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:26379> info replication 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=10.0.0.18:6379,slaves=2,sentinels=3观察新master上状态和日志
[root@slave1 ~]#redis-cli -a centos Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:6379> info replication # Replication role:master connected_slaves:2 slave0:ip=10.0.0.28,port=6379,state=online,offset=261044,lag=1 slave1:ip=10.0.0.8,port=6379,state=online,offset=261044,lag=1 master_replid:d0986944509eefec498f58c3eef54240d373ce31 master_replid2:71aa5e09a5f6c2034a5e8f853e3ec0975d9d0ff3 master_repl_offset:261309 second_repl_offset:8732 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:261309 [root@slave1 ~]#cat /var/log/redis/sentinel.log 7529:X 24 Oct 2020 22:19:03.307 # +sdown slave 10.0.0.8:6379 10.0.0.8 6379 @ mymaster 10.0.0.18 6379 7529:X 24 Oct 2020 22:36:27.173 # -sdown slave 10.0.0.8:6379 10.0.0.8 6379 @ mymaster 10.0.0.18 6379手动让主节点下线
sentinel failover <masterName>范例: 手动故障转移
[root@master ~]#sed -ri "s/^(replica-priority).*/\1 10/" /etc/redis.conf [root@master ~]#grep replica-priority /etc/redis.conf replica-priority 10 #指定优先级,值越小sentinel会优先将之选为新的master,默为值为100 [root@master ~]#redis-cli -a centos -p 26379 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. 127.0.0.1:26379> sentinel failover mymaster OK 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=10.0.0.8:6379,slaves=2,sentinels=3Redis 官方客户端:https://redis.io/clients
java 客户端连接Redis:https://github.com/xetorthio/jedis/blob/master/pom.xml
#jedis/pom.xml 配置连接redis <properties> <redishosts>localhost:6379,localhost:6380,localhost:6381,localhost:6382,localhost:6383,localhost:6384,localhost:6385</redis-hosts> <sentinelhosts>localhost:26379,localhost:26380,localhost:26381</sentinel-hosts> <clusterhosts>localhost:7379,localhost:7380,localhost:7381,localhost:7382,localhost:7383,localhost:7384,localhost:7385</cluster-hosts> <github.global.server>github</github.global.server> </properties>java客户端连接单机的redis是通过Jedis来实现的,java代码用的时候只要创建Jedis对象就可以建多个Jedis连接池来连接redis,应用程序再直接调用连接池即可连接Redis。而Redis为了保障高可用,服务一般都是Sentinel部署方式,当Redis服务中的主服务挂掉之后,会仲裁出另外一台Slaves服务充当Master。这个时候,我们的应用即使使用了Jedis 连接池,如果Master服务挂了,应用将还是无法连接新的Master服务,为了解决这个问题, Jedis也提供了相应的Sentinel实现,能够在Redis Sentinel主从切换时候,通知应用,把应用连接到新的Master服务。
Redis Sentinel的使用也是十分简单的,只是在JedisPool中添加了Sentinel和MasterName参数,JRedis Sentinel底层基于Redis订阅实现Redis主从服务的切换通知,当Reids发生主从切换时,Sentinel会发送通知主动通知Jedis进行连接的切换,JedisSentinelPool在每次从连接池中获取链接对象的时候,都要对 连接对象进行检测,如果此链接和Sentinel的Master服务连接参数不一致,则会关闭此连接,重新获取新的Jedis连接对象。
在哨兵sentinel机制中,可以解决redis高可用问题,即当master故障后可以自动将slave提升为master,从而可以保证redis服务的正常使用,但是无法解决redis单机写入的瓶颈问题,即单机redis写入性能受限于单机的内存大小、并发数量、网卡速率等因素。
早期Redis 分布式集群部署方案:
客户端分区:由客户端程序决定key写分配和写入的redis node,但是需要客户端自己处理写入分配、高可用管理和故障转移等代理方案:基于三方软件实现redis proxy,客户端先连接之代理层,由代理层实现key的写入分配,对客户端来说是有比较简单,但是对于集群管理节点增减相对比较麻烦,而且代理本身也是单点和性能瓶颈。redis 3.0版本之后推出了无中心架构的redis cluster机制,在无中心的redis集群当中,其每个节点保存当前节点数据和整个集群状态,每个节点都和其他所有节点连接
Redis Cluster特点如下:
所有Redis节点使用(PING机制)互联集群中某个节点的是否失效,是由整个集群中超过半数的节点监测都失效,才能算真正的失效客户端不需要proxy即可直接连接redis,应用程序中需要配置有全部的redis服务器IPredis cluster把所有的redis node 平均映射到 0-16383个槽位(slot)上,读写需要到指定的redis node上进行操作,因此有多少个redis node相当于redis 并发扩展了多少倍,每个redis node 承 担16384/N个槽位Redis cluster预先分配16384个(slot)槽位,当需要在redis集群中写入一个key -value的时候,会使用CRC16(key) mod 16384之后的值,决定将key写入值哪一个槽位从而决定写入哪一个Redis节点上,从而有效解决单机瓶颈。假如三个主节点分别是:A,B,C三个节点,采用哈希槽(hash slot)的方式来分配16384个slot的活,它们三个节点分别承担的slot 区间可以是:
节点A覆盖:0-5460 节点B覆盖:5461-10922 节点C覆盖:10923-16383Redis cluster的架构虽然解决了并发的问题,但是又引入了一个新的问题,每个Redis master的高可用如何解决?
那就是对每个master 节点都实现主从复制,从而实现 redis 高可用性
环境A:3台服务器,每台服务器启动6379和6380两个redis 服务实例,适用于测试环境 环境B:6台服务器,分别是三组master/slave,适用于生产环境
#集群节点 10.0.0.8 10.0.0.18 10.0.0.28 10.0.0.38 10.0.0.48 10.0.0.58 #预留服务器扩展使用 10.0.0.68 10.0.0.78说明:Redis 5.X 和之前版本相比有很多变化,以下分别介绍两个版本5.X和4.X的配置
redis cluster 有多种部署方法
原生命令安装 理解Redis Cluster架构 生产环境不使用官方工具安装 高效、准确 生产环境可以使用自主研发 可以实现可视化的自动化部署官方文档:https://redis.io/topics/cluster-tutorial
redis cluster 相关命令 范例:查看 --cluster 选项帮助
[root@centos8 ~]#redis-cli --cluster help Cluster Manager Commands: create host1:port1 ... hostN:portN --cluster-replicas <arg> check host:port --cluster-search-multiple-owners info host:port fix host:port --cluster-search-multiple-owners reshard host:port --cluster-from <arg> --cluster-to <arg> --cluster-slots <arg> --cluster-yes --cluster-timeout <arg> --cluster-pipeline <arg> --cluster-replace rebalance host:port --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 set-timeout host:port milliseconds import host:port --cluster-from <arg> --cluster-copy --cluster-replace help For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.范例: 查看CLUSTER 指令的帮助
[root@centos8 ~]#redis-cli -a centos --no-auth-warning cluster help 1) CLUSTER <subcommand> arg arg ... arg. Subcommands are: 2) ADDSLOTS <slot> [slot ...] -- Assign slots to current node. 3) BUMPEPOCH -- Advance the cluster config epoch. 4) COUNT-failure-reports <node-id> -- Return number of failure reports for <node-id>. 5) COUNTKEYSINSLOT <slot> - Return the number of keys in <slot>. 6) DELSLOTS <slot> [slot ...] -- Delete slots information from current node. 7) FAILOVER [force|takeover] -- Promote current replica node to being a master. 8) FORGET <node-id> -- Remove a node from the cluster. 9) GETKEYSINSLOT <slot> <count> -- Return key names stored by current node in a slot. 10) FLUSHSLOTS -- Delete current node own slots information. 11) INFO - Return onformation about the cluster. 12) KEYSLOT <key> -- Return the hash slot for <key>. 13) MEET <ip> <port> [bus-port] -- Connect nodes into a working cluster. 14) MYID -- Return the node id. 15) NODES -- Return cluster configuration seen by node. Output format: 16) <id> <ip:port> <flags> <master> <pings> <pongs> <epoch> <link> <slot> ... <slot> 17) REPLICATE <node-id> -- Configure current node as replica to <node-id>. 18) RESET [hard|soft] -- Reset current node (default: soft). 19) SET-config-epoch <epoch> - Set config epoch of current node. 20) SETSLOT <slot> (importing|migrating|stable|node <node-id>) -- Set slot state. 21) REPLICAS <node-id> -- Return <node-id> replicas. 22) SLOTS -- Return information about slots range mappings. Each range is made of: 23) start, end, master and replicas IP addresses, ports and ids所有6台主机都执行以下配置,以redis-node1为例
[root@redis-node1 ~]#yum -y install redis 每个节点都要修改redis.conf配置文件,必须都开启cluster功能的参数,这里以redis-node1为例[root@redis-node1 ~]#cat init.sh #!/bin/bash sed -i -e "s/bind 127.0.0.1/bind 0.0.0.0/" -e "s/^# masterauth.*/masterauth centos/" -e "s/^# requirepass .*/requirepass centos/" -e "/# cluster-enabled yes/a cluster-enabled yes" -e "/# cluster-config-file nodes-6379.conf/a cluster-config-file nodes-6379.conf" -e "/# cluster-require-full-coverage yes/c cluster-require-full-coverage no" /etc/redis.conf echo -e "net.core.somaxconn = 1024\nvm.overcommit_memory = 1" >> /etc/sysctl.conf sysctl -p echo never > /sys/kernel/mm/transparent_hugepage/enabled echo "echo never > /sys/kernel/mm/transparent_hugepage/enabled" >> /etc/rc.d/rc.local chmod +x /etc/rc.d/rc.local systemctl enable --now redis 验证当前Redis服务状态:以redis-node1为例#开启了16379的cluster的端口,实际的端口=redis port + 10000 [root@redis-node1 ~]#ss -ntl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 0.0.0.0:22 0.0.0.0:* LISTEN 0 100 127.0.0.1:25 0.0.0.0:* LISTEN 0 511 0.0.0.0:16379 0.0.0.0:* LISTEN 0 511 0.0.0.0:6379 0.0.0.0:* LISTEN 0 128 [::]:22 [::]:* LISTEN 0 100 [::1]:25 [::]:* #注意:进程有[cluster]状态 [root@redis-node1 ~]#ps aux | grep redis redis 2017 0.1 0.6 53524 5124 ? Ssl 14:49 0:00 /usr/bin/redis-server 0.0.0.0:6379 [cluster] root 2151 0.0 0.1 12112 984 pts/0 S+ 14:55 0:00 grep --color=auto redis范例: 查看指定master节点的slave节点信息
[root@redis-node1 ~]#redis-cli -a centos cluster nodes Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. cbb5606890cf491d23379e426c61f62fc3a0732e 10.0.0.38:6379@16379 slave c5fd06610cd05c760e3fcfb60ad3b4351ce6b309 0 1603610101333 4 connected 1cd30e11cc46cffa0e441c456a2ecf2645a72771 10.0.0.18:6379@16379 master - 0 1603610100000 2 connected 5461-10922 4e42a7dacf7642810aa398817388e1f120649ba7 10.0.0.58:6379@16379 slave 79643546e59ba0e88477e1678dda30c29113dc56 0 1603610100325 6 connected 79643546e59ba0e88477e1678dda30c29113dc56 10.0.0.28:6379@16379 master - 0 1603610099000 3 connected 10923-16383 e1cb57392effcc88a76060104d131044224a8285 10.0.0.48:6379@16379 slave 1cd30e11cc46cffa0e441c456a2ecf2645a72771 0 1603610099316 5 connected c5fd06610cd05c760e3fcfb60ad3b4351ce6b309 10.0.0.8:6379@16379 myself,master - 0 1603610099000 1 connected 0-5460 #以下命令查看指定master节点的slave节点信息,其中79643546e59ba0e88477e1678dda30c29113dc56 为master中redis-node3节点的ID [root@redis-node1 ~]#redis-cli -a centos --no-auth-warning cluster slaves 79643546e59ba0e88477e1678dda30c29113dc56 1) "4e42a7dacf7642810aa398817388e1f120649ba7 10.0.0.58:6379@16379 slave 79643546e59ba0e88477e1678dda30c29113dc56 0 1603610299010 6 connected"