Redis

Redis

缓存介绍

缓存是为了调节速度不一致的两个或多个不同的物质的速度,在中间对速度较快的一方起到一个加速访问速度较慢的一方的作用

比如 CPU 的一级、二级缓存是保存了 CPU 最近经常访问的数据,内存是保存 CPU 经常访问硬盘的数据,而且硬盘也有大小不一的缓存,甚至是物理服务器的 raid 卡有也缓存
为了起到加速 CPU 访问硬盘数据的目的,因为 CPU 的速度太快了, CPU 需要的数据硬盘往往不能在短时间内满足 CPU 的需求,因此 PCU 缓存、内存、 Raid 卡以及硬盘缓存就在一定程度上满足了 CPU 的数据需求,即 CPU 从缓存读取数据可以大幅提高 CPU 的工作效率
在这里插入图片描述

系统缓存

buffer 与 cache

在这里插入图片描述

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

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

cache 的保存位置

  • 客户端:浏览器
  • 内存:本地服务器、远程服务器
  • 硬盘:本机硬盘、远程服务器硬盘

cache 的特性

  • 自动过期:给缓存的数据加上有效时间,超出时间后自动过期删除
  • 过期时间:强制过期,源网站更新图片后 CDN 是不会更新的,需要强制使图片缓存过期
  • 命中率:即缓存的读取命中率

用户层缓存

DNS 缓存

  • 默认为 60 秒,即 60 秒之内再访问同一个域名就不再进行 DNS 解析
  • 查看 chrome 浏览器的 DNS 缓存:chrome://net-internals/#dns
  • DNS 预获取,仅在HTML5中支持,当一个页面中包含多个域名的时候浏览器会先尝试解析域名并进行缓存,之后再使用的时候即可直接使用不需要再进行DNS 解析

浏览器缓存过期机制

最后修改时间

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

Etag标记

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

过期时间 expires

以上两种都需要发送请求,即不管资源是否过期都要发送请求进行协商,这样会消耗不必要的时间,因此有了缓存的过期时间

Expire 是 HttpHeader 中代表资源的过期时间,由服务器端设置。如果带有 Expire ,则在 Expire 过期前不会发生 Http 请求,直接从缓存中读取。用户强制 F5 例外

第一次请求资源时,响应报文带有资源的过期时间,默认为30天,当前此方式使用的比较多,但是无法保证客
户的时间都是准确并且一致的,因此会加入一个最大生存周期,使用用户本地的时间计算缓存数据是否超过多少天,假如过期时间Expires:为2031年,但是缓存的最大生存周期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
  • 按shift+F5强制刷新,所有缓存不再使用,直接连接服务器,获取最新数据,返回200响应码

cookie 和 session

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

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

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

CDN 缓存

什么是CDN

在这里插入图片描述

内容分发网络(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

用户请求CDN流程

假设您的业务源站域名为www.test.com,域名接入 CDN 开始使用加速服务后,当您的用户发起HTTP 请求时,实际的处理流程如下图所示:

在这里插入图片描述

详细说明如下:

  1. 用户向www.test.com下的某图片资源(如:1.jpg)发起请求,会先向 Local DNS 发起域名解析请求

  2. 当 Local DNS 解析www.test.com时,会发现已经配置了 CNAMEwww.test.com.cdn.dnsv1.com,解析请求会发送至 Tencent DNS(GSLB),GSLB 为腾讯云自主研发的调度体系,会为请求分配最佳节点IP.

  3. Local DNS 获取 Tencent DNS 返回的解析 IP

  4. 用户获取解析 IP。

  5. 用户向获取的 IP 发起对资源 1.jpg 的访问请求。

  6. 若该 IP 对应的节点缓存有 1.jpg,则会将数据直接返回给用户(10),此时请求结束。若该节点未缓存
    1.jpg,则节点会向业务源站发起对 1.jpg 的请求(6、7、8),获取资源后,结合用户自定义配置的缓存
    策略,将资源缓存至节点(9),并返回给用户(10),此时请求结束。

在这里插入图片描述

利用 302 实现转发请求重定向至最优服务器集群

因为中国网络较为复杂,依赖DNS就近解析的调度,仍然会存在部分请求调度失效、调度生效慢等问题。

比如:腾讯云利用在全国部署的302重定向服务器集群,能够为每一个请求实时决策最优的服务器资源,精准解
决小运营商的调度问题,提升用户访问质量, 能最快地把用户引导到最优的服务器节点上,避开性能差或者异常的节点。

CDN 分层缓存

提前对静态内容进行预缓存,避免大量的请求回源,导致主站网络带宽被打满而导致数据无法更新,另外CDN可以将数据根据访问的热度不同而进行不同级别的缓存,例如:访问量最高的资源访问CDN 边缘节点的内存,其次的放在SSD或者SATA,再其次的放在云存储,这样兼顾了速度与成本。
比如: 腾讯云CDN节点,根据用户的数据冷热不同,动态的进行识别,按照cache层次进行数据的存储,在访问频率到40%-90%的数据,首先放在OC边缘节点内存cache中,提供8G-64G的数据空间存储;在访问频率到30%-50%的数据,放在OC节点SSD/SATA硬盘cache中,提供1T-15T的数据空间存猪,其他的比较冷的数据,放在云存储中,采用回源拉取的方式进行处理。这样在成本和效率中计算出最优平衡点,为客户提供服务

CDN主要优势

CDN 有效地解决了目前互联网业务中网络层面的以下问题:

  • 用户与业务服务器地域间物理距离较远,需要进行多次网络转发,传输延时较高且不稳定。
  • 用户使用运营商与业务服务器所在运营商不同,请求需要运营商之间进行互联转发。
  • 用户使用运营商与业务服务器所在运营商不同,请求需要运营商之间进行互联转发。
  • 利用CDN防止和抵御DDos等攻击,实现安全保护

应用层缓存

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

数据层缓存

分布式缓存服务

  • Redis
  • Memcached

数据库

  • nMySQL 查询缓存
  • innodb缓存、MyISAM缓存

硬件缓存
CPU缓存
CPU缓存(L1的数据缓存和L1的指令缓存)、二级缓存、三级缓存

redis介绍

排名:https://db-engines.com/en/ranking

redis特性

  • 速度快: 10W QPS,基于内存,C语言实现
  • 单线程(不需要进行线程间的切换)
  • 持久化
  • 支持多种数据结构
  • 支持多种编程语言
  • 功能丰富: 支持Lua脚本,发布订阅,事务,pipeline等功能
  • 简单: 代码短小精悍(单机核心代码只有23000行左右),单线程开发容易,不依赖外部库,使用简单
  • 主从复制
  • 支持高可用和分布式

单线程为何如此之快?

  • 纯内存
  • 非阻塞
  • 避免线程切换和竞态消耗

单线程

在这里插入图片描述

注意事项:

  • 一次只运行一条命令
  • 拒绝长(慢)命令:keys, flushall, flushdb, slow lua script, mutil/exec, operate big value(collection)
  • 其实不是单线程: 早期版本是单进程单线程,3版本后实际还有其它的线程, fysnc file descriptor,close file
    descriptor

redis 对比 memcached

  • 支持数据的持久化:可以将内存中的数据保持在磁盘中,重启redis服务或者服务器之后可以从备份文件中恢复数据到内存继续使用
  • 支持更多的数据类型:支持string(字符串)、hash(哈希数据)、list(列表)、set(集合)、zset(有序集合)
  • 支持数据的备份:可以实现类似于数据的master-slave模式的数据备份,另外也支持使用快照+AOF
  • 支持更大的value数据:memcache单个key value最大只支持1MB,而redis最大支持512MB(生产不建议超过2M,性能受影响)
  • 在Redis6版本前,Redis 是单线程,而memcached是多线程,所以单机情况下没有memcached 并发高,性能更好,但redis 支持分布式集群以实现更高的并发,单Redis实例可以实现数万并发
  • 支持集群横向扩展:基于redis cluster的横向扩展,可以实现分布式集群,大幅提升性能和数据安全性
  • 都是基于 C 语言开发

在这里插入图片描述

redis 典型应用场景

  • 数据变化量大的,比如购物车,点赞数量,评论,关注量等
  • Session 共享:常见于web集群中的Tomcat或者PHP中多web服务器session共享
  • 缓存:数据查询、电商网站商品信息、新闻内容
  • 地理位置: 基于GEO(地理信息定位),实现摇一摇,附近的人,外卖等功能

Redis 安装及连接

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

yum安装(版本较老)

yum -y install epel-release
yum -y install redis
yum info redis
systemctl enable --now redis
pstree -p |grep redis
redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> info

脚本安装:

#!/bin/bash
. /etc/init.d/functions
VERSION=redis-5.0.9
DIR1=/apps/redis
PASSWORD=centos
install(){
yum -y install make wget gcc tcl &> /dev/null || { action "安装所需包失败, 请检测包
或网络配置" false;exit;}
wget http://download.redis.io/releases/${VERSION}.tar.gz &> /dev/null || { action "Redis 源码下载失败" false; exit; }
tar xf $VERSION.tar.gz
cd $VERSION/
make  -j 2 &> /dev/null && make PREFIX=${DIR1} install &> /dev/null && action "Redis 编译安装>成功" || { action "Redis 编译安装失败" false;exit; }
ln -s ${DIR1}/bin/* /usr/bin/
mkdir -p ${DIR1}/{etc,data,log,run}
cd
cp $VERSION/redis.conf $DIR1/etc 
sed -i -e "s/bind 127.0.0.1/bind 0.0.0.0/" -e "/# requirepass/a requirepass ${PASSWORD}"  -e "/^dir .*/c dir ${DIR1}/data/" -e "/logfile .*/c logfile ${DIR1}/log/redis_6379.log"  -e "/^pidfile .*/c pidfile ${DIR1}/run/redis_6379.pid" ${DIR1}/etc/redis.conf
if id redis &> /dev/null;then
    action "redis 用户已经存在" false
else
    useradd -r -s /sbin/nologin redis
	action "redis 用户创建成功"
fi
chown -R redis.redis ${DIR1}
cat >> /etc/sysctl.conf <<EOF
net.core.somaxconn = 1024
vm.overcommit_memory = 1
EOF
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
/etc/rc.d/rc.local
cat > /lib/systemd/system/redis.service <<EOF
[Unit]
Description=Redis persistent key-value database
After=network.target
[Service]
ExecStart=${DIR1}/bin/redis-server ${DIR1}/etc/redis.conf --supervised systemd
ExecStop=/bin/kill -s QUIT \$MAINPID
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now redis &> /dev/null && action "redis 服务启动成功" || { action "redis 服务启动失败" false;exit; }
}
install

编译安装

下载当前最新release版本 redis 源码包
网站:http://download.redis.io/releases/

编译安装

  • 获取软件安装包,安装编译环境
root@localhost ~]# yum -y install make gcc tcl
[root@localhost ~]# wget http://download.redis.io/releases/redis-5.0.9.tar.gz
[root@localhost ~]# tar xf redis-5.0.9.tar.gz
  • 编译安装
[root@localhost ~]# cd redis-5.0.9/
[root@localhost redis-5.0.9]# cd src/
[root@localhost src]# make
[root@localhost src]# make PREFIX=/apps/redis install
  • 配置环境变量
[root@localhost src]# echo "PATH=/apps/redis/bin:$PATH" >
/etc/profile.d/redis.sh
[root@localhost src]# . /etc/profile.d/redis.sh
  • 目录结构
[root@localhost 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@localhost ~]# mkdir /apps/redis/{etc,log,data,run}
[root@localhost ~]# cp redis-5.0.9/redis.conf /apps/redis/etc/

前台启动 redis
redis-server 是redis 服务器程序

[root@localhost src]# 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
   
[root@localhost src]# redis-server /apps/redis/etc/redis.conf

启动多实例

  • 刚刚启动的案例是6379端口,我们可以在6380端口上开启第二个redis服务
  • 为6380准备相关目录和文件
[root@localhost ~]# mkdir /apps/redis/6380
[root@localhost ~]# cp -ar /apps/redis/* /apps/redis/6380/
[root@localhost ~]# tree -d /apps/redis/6380
/apps/redis/6380
├── 6380
├── bin
├── data
├── etc
├── log
└── run
6 directories
[root@localhost ~]# vim /apps/redis/6380/etc/redis.conf
port 6380
  • 前端启动6380
[root@localhost ~]# redis-server --port 6380
[root@localhost ~]# ss -ntl
State   Recv-Q Send-Q Local Address:Port        Peer Address:Port  
LISTEN   0    128     *:6379           *:*
LISTEN   0    128     *:6380           *:*
LISTEN   0    128     :::6379          :::*
LISTEN   0    128     :::6380          :::*
[root@localhost ~]# redis-cli -p 6380
127.0.0.1:6380> exit
[root@localhost ~]# redis-cli -p 6379
127.0.0.1:6379> exi

解决启动时的三个警告提示

  • tcp-backlog
    • backlog参数控制的是三次握手的时候server端收到client.ack确认号之后的队列值,即全连接队列
[root@localhost ~]# echo "net.core.somaxconn = 1024" >> /etc/sysctl.conf
[root@localhost ~]# sysctl -p
net.core.somaxconn = 1024
  • vm.overcommit_memory

    • 查看警告信息有提示,建议将其值改为1
    • 0 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允
    • 1 表示内核允许分配所有的物理内存,而不管当前的内存状态如何
    • 2 表示内核允许分配超过所有物理内存和交换空间总和的内存
    [root@localhost ~]# echo "vm.overcommit_memory=1" >> /etc/sysctl.conf
    [root@localhost ~]# sysctl -p
    net.core.somaxconn = 1024
    vm.overcommit_memory = 1
    
  • transparent huge pages

    • 警告:您在内核中启用了透明大页面(THP,不同于一般内存页的4k为2M)支持。 这将在Redis中造成延迟和内存使用问题。 要解决此问题,请以root 用户身份运行命令 echo never>
      /sys/kernel/mm/transparent_hugepage/enabled ,并将其添加到您的 /etc/rc.local中,以便在重启后保留设置。禁用THP后,必须重新启动Redis。
[root@localhost ~]# echo never > /sys/kernel/mm/transparent_hugepage/enabled
[root@localhost ~]# echo "echo never >
/sys/kernel/mm/transparent_hugepage/enabled" >> /etc/rc.d/rc.local
[root@localhost ~]# chmod +x /etc/rc.d/rc.local
  • 再次启动redis可以看到警告消除,建议在其它redis服务器上做以上配置

创建 redis 用户

[root@localhost ~]# useradd -r -s /sbin/nologin redis
[root@localhost ~]# chown -R redis.redis /apps/redis/

编辑 redis 服务启动文件

  • 复制其它主机yum安装生成的redis.service文件,进行修改

    [root@localhost ~]# vim /lib/systemd/system/redis.service
    [Unit]
    Description=Redis persistent key-value database
    After=network.target
    [Service]
    ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis.conf --supervised
    systemd
    ExecStop=/bin/kill -s QUIT $MAINPID
    Type=notify
    User=redis
    Group=redis
    RuntimeDirectory=redis
    RuntimeDirectoryMode=0755
    [Install]
    WantedBy=multi-user.target
    

验证 redis 启动

[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl enable --now redis
[root@localhost ~]# ss -ntl
State   Recv-Q Send-Q Local Address:Port         Peer Address:Port
LISTEN   0    511     127.0.0.1:6379              *:*

使用客户端连接 redis

  • 格式
redis-cli -h IP/HOSTNAME -p PORT -a PASSWORD 

[root@localhost ~]# redis-cli
127.0.0.1:6379> info
127.0.0.1:6379> exit

创建命令软链接

[root@localhost ~]# ln -s /apps/redis/bin/ /usr/bin/ 

编译安装后的命令

[root@localhost ~]# ll /apps/redis/bin/
总用量 32772
-rwxr-xr-x. 1 redis redis 4367128 73 21:19 redis-benchmark
-rwxr-xr-x. 1 redis redis 8125424 73 21:19 redis-check-aof
-rwxr-xr-x. 1 redis redis 8125424 73 21:19 redis-check-rdb
-rwxr-xr-x. 1 redis redis 4808096 73 21:19 redis-cli
lrwxrwxrwx. 1 redis redis    12 73 21:19 redis-sentinel -> redis-server
-rwxr-xr-x. 1 redis redis 8125424 73 21:19 redis-server
工具作用
redis-benchmarkredis 性能测试工具
redis-check-aofAOF文件检查工具(记录操作的命令)
redis-check-rdbRDB文件检查工具(快照)
redis-cli客户端工具
redis-sentinel -> redis-server哨兵,软链接到server
redis-serverredis 服务启动命令

连接到 Redis

客户端连接 redis

  • 本机无密码连接
[root@localhost ~]# redis-cli
127.0.0.1:6379>
  • 跨主机无密码连接
[root@localhost ~]# redis-cli -h 192.168.135.10 -p 6379
192.168.175.149:6379>
  • 跨主机密码连接
[root@localhost ~]# vim /apps/redis/etc/redis.conf
requirepass centos
[root@localhost ~]# systemctl restart redis
[root@localhost ~]# redis-cli -h 192.168.135.10 -p 6379 -a centos --no-auth-
warning
192.168.175.149:6379>

程序连接 Redis

  • redis 支持多种开发语言访问https://redis.io/clients

shell 连接方式

[root@localhost ~]# vim redis_test.sh
#!/bin/bash
NUM=`seq 1 10000`
PASS=centos
for i in ${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 "一万个key写入到Redis完成"
[root@localhost ~]# vim /apps/redis/etc/redis.conf#这边临时关闭RDB,不然会报错,因为没有指定rdb路径
save ""
#save 900 1
#save 300 10
#save 60 10000
[root@localhost ~]# systemctl restart redis
[root@localhost ~]# time bash redis_test.sh
一万个key写入到Redis完成
real  0m22.874s
user  0m3.885s
sys   0m17.958s
[root@localhost ~]# redis-cli
127.0.0.1:6379> auth centos
OK
127.0.0.1:6379> keys *
127.0.0.1:6379> get key-996
"value-996"
127.0.0.1:6379> flushdb   # 清空当前库的数据
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> flushall   # 清空所有的数据
OK

python 连接方式

  • python 多种开发库,可以支持连接redis
  • 安装python运行环境
[root@localhost ~]# yum -y install python3 python3-redis 

编写python程序

[root@localhost ~]# vim 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@localhost ~]# python3 redis_test.py
  • 验证数据是否正确插入
[root@localhost ~]# redis-cli -a centos --no-auth-warning
127.0.0.1:6379> get k88
"v88"

redis 的多实例

  • 测试环境中经常使用多实例,需要指定不同实例的相应的端口,配置文件,日志文件等相关配置
  • 以编译安装为例实现 redis 多实例
  • 修改配置文件和启动服务
[root@localhost ~]# cd /apps/redis/
[root@localhost redis]# mv etc/redis.conf etc/redis_6379.conf
[root@localhost redis]# vim etc/redis_6379.conf
port 6379
pidfile /apps/redis/run/redis_6379.pid
logfile "/apps/redis/log/redis_6379.log"
dbfilename dumpi_6379.rdb
dir /apps/redis/data
appendfilename "appendonlyi_6379.aof"
[root@localhost redis]# mv /lib/systemd/system/redis.service
/lib/systemd/system/redis_6379.service
[root@localhost redis]# vim /lib/systemd/system/redis_6379.service
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis_6379.conf --
supervised systemd
[root@localhost redis]# systemctl restart redis_6379.service
  • 按照同样的方式,启动6380和6381实例
cp -a etc/redis_6379.conf etc/redis_6380.conf
sed -i "s/6379/6380/g" etc/redis_6380.conf
cp -a /lib/systemd/system/redis_6379.service
/lib/systemd/system/redis_6380.service
sed -i "s/6379/6380/g" /lib/systemd/system/redis_6380.service
systemctl enable --now redis_6380.service

cp -a etc/redis_6379.conf etc/redis_6381.conf
sed -i "s/6379/6381/g" etc/redis_6381.conf
cp -a /lib/systemd/system/redis_6379.service
/lib/systemd/system/redis_6381.service
sed -i "s/6379/6381/g" /lib/systemd/system/redis_6381.service
systemctl daemon-reload
systemctl enable --now redis_6381.service
  • 验证端口号
[root@localhost redis]# ss -ntl
State   Recv-Q Send-Q    Local Address:Port           Peer
Address:Port
LISTEN   0    511           *:6379               
 *:*
LISTEN   0    511           *:6380               
 *:*
LISTEN   0    511           *:6381               
 *:*
  • 查看文件结构目录
[root@localhost redis]# tree
.
├── bin
│  ├── redis-benchmark
│  ├── redis-check-aof
│  ├── redis-check-rdb
│  ├── redis-cli
│  ├── redis-sentinel -> redis-server
│  └── redis-server
├── data
├── 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, 15 files

redis 配置和优化

redis 主要配置项

  • redis常用配置参数
bind 0.0.0.0 #监听地址,可以用空格隔开后多个监听IP
protected-mode yes #redis3.2之后加入的新特性,在没有设置bind IP和密码的时候,redis只允许访问127.0.0.1:6379,可以远程连接,但当访问将提示警告信息并拒绝远程访问
port 6379 #监听端口,默认6379/tcp
tcp-backlog 511 #三次握手的时候server端收到client ack确认号之后的队列值,即全连接队列长度
timeout 0 #客户端和Redis服务端的连接超时时间,默认是0,表示永不超时
tcp-keepalive 300 #tcp 会话保持时间300s
daemonize no #默认no,即直接运行redis-server程序时,不作为守护进程运行,而是以前台方式运行,如果想在后台运行需改成yes,当redis作为守护进程运行的时候,它会写一个 pid到/var/run/redis.pid 文件
supervised no #和OS相关参数,可设置通过upstart(uban)和systemd管理Redis守护进程,centos7后都使用systemdpidfile ,实际还是systemced启动,/var/run/redis_6379.pid #pid文件路径,可以修改为/apps/redis/run/redis_6379.pid
loglevel notice #日志级别
logfile "/path/redis.log" #日志路径,示例:logfile"/apps/redis/log/redis_6379.log"
databases 16 #设置数据库数量,默认:0-15,共16个库
always-show-logo yes #在启动redis 时是否显示或在日志中记录记录redis的logo
  • 快照配置

    save 900 1 #在900秒内有1个key内容发生更改,就执行快照机制
    save 300 10 #在300秒内有10个key内容发生更改,就执行快照机制
    save 60 10000 #60秒内如果有10000个key以上的变化,就自动快照备份
    stop-writes-on-bgsave-error yes #默认为yes时,可能会因空间满等原因快照无法保存出错时,会
    禁止redis写入操作,生产建议为no #此项只针对配置文件中的自动save有效
    rdbcompression yes #持久化到RDB文件时,是否压缩,"yes"为压缩,"no"则反之
    rdbchecksum yes #是否对备份文件开启RC64校验,默认是开启
    dbfilename dump.rdb #快照文件名
    dir ./ #快照文件保存路径,示例:dir "/apps/redis/data"
    
  • 主从复制相关配置

    # replicaof <masterip> <masterport> #指定复制的master主机地址和端口,5.0版之前的指令为
    slaveof
    # masterauth <master-password> #指定复制的master主机的密码
    replica-serve-stale-data yes #当从库同主库失去连接或者复制正在进行,从机库有两种运行方
    式:
    1、设置为yes(默认设置),从库会继续 响应客户端的读请求,此为建议值
    2、设置为no,除去特定命令外的任何请求都会返回一个错误"SYNC with master in progress"。
    replica-read-only yes #是否设置从库只读,建议值为yes,否则主库同步从库时可能会覆盖数据,造
    成数据丢失
    repl-diskless-sync no #是否使用socket方式复制数据(无盘同步),新slave第一次连接master时需要做数据的全量同步,redis server就要从内存dump出新的RDB文件,然后从master传到slave,有
    两种方式把RDB文件传输给客户端:
    1、基于硬盘(disk-backed):为no时,master创建一个新进程dump生成RDB磁盘文件,RDB完成之后
    由
    父进程(即主进程)将RDB文件发送给slaves,此为默认值
    
    2、基于socket(diskless):master创建一个新进程直接dump RDB至slave的网络socket,不经过
    主进程和硬盘
    #推荐使用基于硬盘(为no),是因为RDB文件创建后,可以同时传输给更多的slave,但是基于socket(为
    yes), 新slave连接到master之后得逐个同步数据。只有当磁盘I/O较慢且网络较快时,可用
    diskless(yes),否则一般建议使用磁盘(no)
    repl-diskless-sync-delay 5 #diskless时复制的服务器等待的延迟时间,设置0为关闭,在延迟时
    间内到达的客户端,会一起通过diskless方式同步数据,但是一旦复制开始,master节点不会再接收新
    slave的复制请求,直到下一次同步开始才再接收新请求。即无法为延迟时间后到达的新副本提供服务,新
    副本将排队等待下一次RDB传输,因此服务器会等待一段时间才能让更多副本到达。推荐值:30-60
    repl-ping-replica-period 10 #slave根据master指定的时间进行周期性的PING master,用于监
    测master状态,默认10s
    repl-timeout 60 #复制连接的超时时间,需要大于repl-ping-slave-period,否则会经常报超时
    repl-disable-tcp-nodelay no #是否在slave套接字发送SYNC之后禁用 TCP_NODELAY,如果选"yes",Redis将合并多个报文为一个大的报文,从而使用更少数量的包向slaves发送数据,但是将使数
    据传输到slave上有延迟,Linux内核的默认配置会达到40毫秒,如果 "no" ,数据传输到slave的延迟将
    会减少,但要使用更多的带宽
    repl-backlog-size 512mb #复制缓冲区内存大小,当slave断开连接一段时间后,该缓冲区会累积复
    制副本数据,因此当slave 重新连接时,通常不需要完全重新同步,只需传递在副本中的断开连接后没有同
    步的部分数据即可。只有在至少有一个slave连接之后才分配此内存空间,建议建立主从时此值要调大一些或
    在低峰期配置,否则会导致同步到slave失败
    repl-backlog-ttl 3600 #多长时间内master没有slave连接,就清空backlog缓冲区
    replica-priority 100 #当master不可用,哨兵Sentinel会根据slave的优先级选举一个master,
    此值最低的slave会当选master,而配置成0,永远不会被选举,一般多个slave都设为一样的值,让其自
    动选择
    #min-replicas-to-write 3 #至少有3个可连接的slave,mater才接受写操作
    #min-replicas-max-lag 10 #和上面至少3个slave的ping延迟不能超过10秒,否则master也将停止
    写操作
    requirepass foobared #设置redis连接密码,之后需要AUTH pass,如果有特殊符号,用" "引起来,
    生产建议设置
    rename-command #重命名一些高危命令,示例:rename-command FLUSHALL "" 禁用命令
     #示例: rename-command del areyouok
    
    
  • 客户端配置

    maxclients 10000 #Redis最大连接客户端
    maxmemory <bytes> #redis使用的最大内存,单位为bytes字节,0为不限制,建议设为物理内存一
    半,8G内存的计算方式8(G)*1024(MB)1024(KB)*1024(Kbyte),需要注意的是缓冲区是不计算在
    maxmemory内,生产中如果不设置此项,可能会导致BOOM
    appendonly no #是否开启AOF日志记录,默认redis使用的是rdb方式持久化,这种方式在许多应用中已
    经足够用了,但是redis如果中途宕机,会导致可能有几分钟的数据丢失(取决于dump数据的间隔时间),根据save来策略进行持久化,Append Only File是另一种持久化方式,可以提供更好的持久化特性,Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件,每次启动时Redis都会先把这个文件
    的数据读入内存里,先忽略RDB文件。默认不启用此功能
    appendfilename "appendonly.aof" #文本文件AOF的文件名,存放在dir指令指定的目录中
    appendfsync everysec #aof持久化策略的配置
    #no表示由操作系统保证数据同步到磁盘,Linux的默认fsync策略是30秒,最多会丢失30s的数据(写入aof才进行下一个操作)
    #always表示每次写入都执行fsync,以保证数据同步到磁盘,安全性高,性能较差(用户回车后同步)
    #everysec表示每秒执行一次fsync,可能会导致丢失这1s数据,此为默认值,也生产建议值
    #同时在执行bgrewriteaof操作和主进程写aof文件的操作,两者都会操作磁盘,而bgrewriteaof(重写)样就会造成主进程在写aof文件的时候出现阻塞的情形,以下参数实现控制
    
    no-appendfsync-on-rewrite no #在aof rewrite期间,是否对aof新记录的append暂缓使用文件同
    步策略,主要考虑磁盘IO开支和请求阻塞时间。
    #默认为no,表示"不暂缓",新的aof记录仍然会被立即同步到磁盘,是最安全的方式,不会丢失数据,但是
    要忍受阻塞的问题
    #为yes,相当于将appendfsync设置为no,这说明并没有执行磁盘操作,只是写入了缓冲区,因此这样并不
    会造成阻塞(因为没有竞争磁盘),但是如果这个时候redis挂掉,就会丢失数据。丢失多少数据呢?
    Linux的默认fsync策略是30秒,最多会丢失30s的数据,但由于yes性能较好而且会避免出现阻塞因此比较
    推荐
    #rewrite 即对aof文件进行整理,将空闲空间回收,从而可以减少恢复数据时间
    auto-aof-rewrite-percentage 100 #当Aof log增长超过指定百分比例时,重写AOF文件,设置为0
    表示不自动重写Aof日志,重写是为了使aof体积保持最小,但是还可以确保保存最完整的数据
    auto-aof-rewrite-min-size 64mb #触发aof rewrite的最小文件大小
    aof-load-truncated yes #是否加载由于某些原因导致的末尾异常的AOF文件(主进程被kill/断电),建议yes
    aof-use-rdb-preamble no #redis4.0新增RDB-AOF混合持久化格式,在开启了这个功能之后,AOF重
    写产生的文件将同时包含RDB格式的内容和AOF格式的内容,其中RDB格式的内容用于记录已有的数据,而
    AOF格式的内容则用于记录最近发生了变化的数据,这样Redis就可以同时兼有RDB持久化和AOF持久化的优
    点(既能够快速地生成重写文件,也能够在出现问题时,快速地载入数据),默认为no,即不启用此功能
    lua-time-limit 5000 #lua脚本的最大执行时间,单位为毫秒
    cluster-enabled yes #是否开启集群模式,默认不开启,即单机模式
    cluster-config-file nodes-6379.conf #由node节点自动生成的集群配置文件名称
    cluster-node-timeout 15000 #集群中node节点连接超时时间,单位ms,超过此时间,会踢出集群
    cluster-replica-validity-factor 10 #单位为次,在执行故障转移的时候可能有些节点和master断开一段时间导致数据比较旧,这些节点就不适用于选举为master,超过这个时间的就不会被进行故障转移,
    不能当选master,计算公式:(node-timeout * replica-validity-factor) + repl-
    pingreplica-period
    cluster-migration-barrier 1 #集群迁移屏障,一个主节点至少拥有1个正常工作的从节点,即如果
    主节点的slave节点故障后会将多余的从节点分配到当前主节点成为其新的从节点。
    cluster-require-full-coverage yes #集群请求槽位全部覆盖,如果一个主库宕机且没有备库就会
    出现集群槽位不全,那么yes时redis集群槽位验证不全,就不再对外提供服务(对key赋值时,会出现
    CLUSTERDOWN The cluster is down的示,cluster_state:fail,但ping 仍PONG),而no则可以继
    续使用,但是会出现查询数据查不到的情况(因为有数据丢失)。生产建议为no
    cluster-replica-no-failover no #如果为yes,此选项阻止在主服务器发生故障时尝试对其主服务器
    进行故障转移。 但是,主服务器仍然可以执行手动强制故障转移,一般为no
    #Slow log 是 Redis 用来记录超过指定执行时间的日志系统,执行时间不包括与客户端交谈,发送回复
    等I/O操作,而是实际执行命令所需的时间(在该阶段线程被阻塞并且不能同时为其它请求提供服务),由于
    slow log 保存在内存里面,读写速度非常快,因此可放心地使用,不必担心因为开启 slow log 而影响
    Redis 的速度
    slowlog-log-slower-than 10000 #以微秒为单位的慢日志记录,为负数会禁用慢日志,为0会记录每
    个命令操作。默认值为10ms,一般一条命令执行都在微秒级,生产建议设为1ms
    slowlog-max-len 128 #最多记录多少条慢日志的保存队列长度,达到此长度后,记录新命令会将最旧的命令从命令队列中删除,以此滚动删除,即,先进先出,队列固定长度,默认128,值偏小,生产建议设为1000以

CONFIG 动态修改配置

  • config 命令用于查看当前redis配置、以及不重启redis服务实现动态更改redis配置等
  • 注意:不是所有配置都可以动态修改,且此方式无法持久保存
redis 127.0.0.1:6379> CONFIG SET parameter value
时间复杂度:O(1)
CONFIG SET 命令可以动态地调整 Redis 服务器的配置(configuration)而无须重启。
redis 127.0.0.1:6379> CONFIG GET slowlog-max-len
1) "slowlog-max-len"
2) "1024"
redis 127.0.0.1:6379> CONFIG SET slowlog-max-len 10086
OK
redis 127.0.0.1:6379> CONFIG GET slowlog-max-len
1) "slowlog-max-len"
2) "10086"
  • 设置连接密码
#设置连接密码
127.0.0.1:6379> CONFIG SET requirepass centos
OK
#查看连接密码
127.0.0.1:6379> CONFIG GET requirepass
1) "requirepass"
2) "centos"
  • 获取当前配置
#奇数行为键,偶数行为值
127.0.0.1:6379> CONFIG GET *
#查看bind
127.0.0.1:6379> CONFIG GET bind
1) "bind"
2) "0.0.0.0"
#有些设置无法修改
127.0.0.1:6379> CONFIG SET bind 127.0.0.1
(error) ERR Unsupported CONFIG parameter: bind
  • 更改最大内存
127.0.0.1:6379> CONFIG SET maxmemory 8589934592
OK
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "8589934592"

慢查询

  • 可以通过config set命令动态修改参数,并使配置持久化到配置文件中

    config set slowlog-log-slower-than 20000  #用来设置慢查询例表的大小,默认128,当有新的记录进来时,会把旧的记录处理掉,储存新的记录
    config set slowlog-max-len 1000   #控制查询时间
    config rewrite
    
  • 获取慢查询日志,将慢查询的时间改为1微秒

    127.0.0.1:6379> config set slowlog-log-slower-than 1
    127.0.0.1:6379> config set slowlog-max-len 1000
    127.0.0.1:6379> SLOWLOG len
    # 获取慢查询日志列表当前的长度
    (integer) 2
    127.0.0.1:6379> SLOWLOG get
    1) 1) (integer) 2
     2) (integer) 1625544379
     3) (integer) 1
     4) 1) "SLOWLOG"
       2) "len"
     5) "127.0.0.1:40294"
     6) ""
    2) 1) (integer) 1
     2) (integer) 1625544372
     3) (integer) 4
     4) 1) "config"
       2) "set"
       3) "slowlog-max-len"
       4) "1000"
     5) "127.0.0.1:40294"
     6) ""
    3) 1) (integer) 0
     2) (integer) 1625544363
     3) (integer) 3
     4) 1) "config"
       2) "set"
       3) "slowlog-log-slower-than"
       4) "1"
     5) "127.0.0.1:40294"
     6) "
    
  • 可以看到每个慢查询日志有4个属性组成,分别是慢查询日志的标识id、发生时间戳、命令耗时、执行命令和参数

  • 慢查询日志重置

127.0.0.1:6379> slowlog reset
OK
127.0.0.1:6379> slowlog len
(integer) 0

redis持久化方式

在这里插入图片描述

RDB持久化(二进制文件)

  • RDB持久化就是把当前数据生成快照保存到硬盘里
    • RDB 是一个非常紧凑的文件,恢复速度要比AOF快
    • RDB的数据没法做到实时持久化/秒级。因为每次bgsave都要执行fork进程,属于重量级操作
    • redis如果意外宕掉的话,会丢失最后一次快照后的所有修改

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oFZyHHL6-1662433651369)(E:\资料\我整理的笔记\image\redis1.png)]

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vtyBGg1D-1662433651370)(E:\资料\我整理的笔记\image\redis.png)]

[root@localhost redis]# pstree -p |grep redis-server;ll -h /apps/redis/data/
|-redis-server(6831)-+-{redis-server}(6849)
|          |-{redis-server}(6850)
|           `-{redis-server}(6851)
|-redis-server(34300)-+-{redis-server}(34301)
|           |-{redis-server}(34302)
|           `-{redis-server}(34303)
总用量 204K
-rw-r--r--. 1 redis redis 204K 76 12:28 dumpi_6379.rdb
  • RDB相关配置
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis #编译安装,默认RDB文件存放在启动redis的工作目录,建议明确指定存入目录
  • 实现RDB方式
    • save:同步,会阻塞其它命令,不推荐使用
    • bgsave:异步后台执行,不影响其它命令的执行
      自动: 制定规则,自动执行

AOF持久化

  • AOF持久化:以独立的日志记录每次命令,重启后再执行AOF中的命令
  • AOF是实时持久化,几乎命令敲下的一瞬间就持久化了
  • AOF文件可读性较强,比RDB体积更大

redis启动时加载持久化文件的顺序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tQscGRg9-1662433651372)在这里插入图片描述

1.AOF持久化开启且存在AOF文件时,优先加载AOF文件
2.AOF关闭或AOF文件不存在时,加载RDB文件
3.AOF/RDB加载失败,redis启动失败,打印失败信息
  • 守护进程
    守护进程(daemon)是一类在后台运行的特殊进程,用于执行特定的系统任务。很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭。另一些只在需要的时候才启动,完成任务后就自动结束。

    • 会随着主进程的结束而结束

    • 主进程创建守护进程

      • 守护进程会在主进程代码执行结束后就终止
      • 守护进程内无法再开启子进程,否则抛出异常
  • AOF工作流程图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gpiwFtTN-1662433651373)(E:\资料\我整理的笔记\image\redis2.png)]

  • 启用AOF
# 用AOF功能的正确方式
[root@localhost data]# ll
总用量 204
-rw-r--r--. 1 redis redis 207886 76 12:28 dumpi_6379.rdb
[root@localhost data]# redis-cli
127.0.0.1:6379> config get appendonly
1) "appendonly"
2) "no"
127.0.0.1:6379> config set appendonly yes
127.0.0.1:6379> CONFIG REWRITE
OK
[root@localhost data]# ll
总用量 408
-rw-r--r--. 1 redis redis 207886 76 13:45 appendonlyi_6379.aof
-rw-r--r--. 1 redis redis 207886 76 12:28 dumpi_6379.rdb
  • AOF相关配置
appendonly yes
appendfilename "appendonly-${port}.aof"
appendfsync everysec
dir /path
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated ye

redis常用命令

  • 显示当前节点redis运行状态信息

    127.0.0.1:6379> info
    

3.AOF/RDB加载失败,redis启动失败,打印失败信息


* 守护进程
  守护进程(daemon)是一类在后台运行的特殊进程,用于执行特定的系统任务。很多守护进程在系统引导的时候启动,并且一直运行直到系统关闭。另一些只在需要的时候才启动,完成任务后就自动结束。

  * 会随着主进程的结束而结束

  * 主进程创建守护进程
    * 守护进程会在主进程代码执行结束后就终止
    * 守护进程内无法再开启子进程,否则抛出异常

* AOF工作流程图

[外链图片转存中...(img-gpiwFtTN-1662433651373)]

* 启用AOF

```shell
# 用AOF功能的正确方式
[root@localhost data]# ll
总用量 204
-rw-r--r--. 1 redis redis 207886 7月  6 12:28 dumpi_6379.rdb
[root@localhost data]# redis-cli
127.0.0.1:6379> config get appendonly
1) "appendonly"
2) "no"
127.0.0.1:6379> config set appendonly yes
127.0.0.1:6379> CONFIG REWRITE
OK
[root@localhost data]# ll
总用量 408
-rw-r--r--. 1 redis redis 207886 7月  6 13:45 appendonlyi_6379.aof
-rw-r--r--. 1 redis redis 207886 7月  6 12:28 dumpi_6379.rdb
  • AOF相关配置
appendonly yes
appendfilename "appendonly-${port}.aof"
appendfsync everysec
dir /path
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated ye

redis常用命令

  • 显示当前节点redis运行状态信息

    127.0.0.1:6379> info
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值