NoSQL之 Redis配置与优化

文章目录

NoSQL之 Redis配置与优化

数据库类型

关系型数据库

实例-->数据库-->表(table)-->记录行(row)、数据字段(column)

非关系型数据库

实例-->数据库-->集合(collection)-->键值对(key-value)

非关系型数据库不需要手动建数据库和集合(表)。

关系型数据库SQL 和 非关系型数据库NoSQL 的区别?

SQL NoSQL
存储结构 二维表格结构 不是二维表格结构,不同的NoSQL采用不同的存储方式(键值对、文档、索引、图形结构、时间序列等)
扩展方 纵向扩展(提升单机的硬件性能) 横向扩展(增加服务器节点数量)
事务支持 基于ACID原则,对事务控制更稳定、细粒度更高 基于BASE原则,对事务控制的稳定性和细粒度不如SQL
典型代表 MySQL、PostgreSQL、Oracle、SQL Server Redis Memcached MongoDB ElasticSearch Prometheus Hbase

Redis

  • 定义:一款用C语言开发的,开源的,基于内存运行NoSQL
  • 存储结构:键值对(Key/Value KV)
  • 数据类型:五大基础数据类型 string(字符串) list(列表) hash(哈希/散列) set(集合/无序集合) zset/sorted set(有序集合)
  • 特殊数据类型 HyperLogLogs(基数统计) Bitmaps (位图) geospatial (地理位置)
  • 端口号:TCP/6379

Redis为什么那么快?

1)redis是基于内存运行,数据的读写都是在内存中完成的

2)数据结构简单,直接使用 键值对 的方式存储数据

3)数据读写采用单线程模式,避免了多线程切换带来的CPU性能损耗,同时也不用考虑各种锁的影响

4)采用IO多路复用模型,异步非阻塞IO可以使网络线程处理更多的网络连接请求,提高了网络并发能力

Redis工具

  • 性能检测工具 redis-benchmark -h <redis服务器地址> -p <redis端口> -a <redis密码> -c <并发连接数> -n <总请求数> -d <请求的数据大小> -t <被测试的命令> -q
  • 客户端命令行工具 redis-cli -h <redis服务器地址> -p <redis端口> -a <redis密码> #默认连接 127.0.0.1:6379

redis持久化

1)RDB持久化:定时的将redis在内存的数据进行快照并压缩保存到硬盘里

手动触发:手动执行 bgsave 命令

自动触发:满足配置文件中 save n m 的规则(在n秒内发生了m次数据更新就会自动触发);主从复制在做全量复制时;执行shutdown命令关闭数据库时

工作流程:redis主进程会fork子进程来进行RDB持久化快照保存内存数据到硬盘里,文件名为 dump.rdb

优缺点:RDB持久化保存的文件占用空间较小,网络传输快,恢复速度比AOF更快,性能影响比AOF更小

实时性不如AOF,兼容性较差,持久化期间在fork子进程时会阻塞redis主进程响应客户端命令

2)AOF持久化:实时的以追加的方式将redis写操作命令保存到aof文件里

工作流程:命令追加(将写操作命令追加到aof_buf缓冲区)

文件写入和同步(按照同步策略将缓冲区里的数据同步到硬盘,文件名:appendonly.aof;同步策略:everysec(每秒刷盘一次)、always(每条命令写入都刷盘)、no(让系统自行刷盘))

文件重写(减少aof文件占用空间和加快恢复速度,定时执行bgrewriteaof命令触发)

优缺点:实时性比RDB更好,支持秒级持久化,兼容性较好;

持久化保存的文件占用空间更大,恢复速度更慢,性能影响更大,AOF文件重写期间在fork子进程时也会阻塞redis主进程,且IO压力更大

RDB和AOF的区别可从 工作方式、实时性、占用空间、恢复速度、兼容性、IO性能影响 这几方面进行描述。

redis性能优化

1)设置内存上限(maxmemory),并设置内存数据淘汰策略(maxmemory-policy),一般采用lru或random

2)开启AOF持久化(实时性好),设置AOF刷盘策略为everysec;关闭自动AOF文件重写,采用定期在业务低峰期执行bgrewriteaof命令触发AOF文件重写,减少IO的压力

3)开启自动内存碎片清理(activedefrag yes)

4)缩短键值对存储长度,避免存储bigkey导致操作耗时(建议string类型数据控制在20KB以内,hash、list、set、zset控制元素数量在5000以内)

5)给key设置合理的过期时间,尽量避免大量key集中过期

6)开启lazy-free机制(lazyfree-lazy-* yes),将删除过期key的操作放到后台线程执行,减少大量的删除操作对redis主进程的阻塞

7)尽量使用物理机而非虚拟机部署redis服务,使用高速固态硬盘作为AOF日志的写入盘

8)使用分布式架构(主从复制、哨兵、集群)实现读写分离、分散bigkey来提升读写速度,并实现高可用

9)禁用内存大页(echo never > /sys/kernel/mm/transparent_hugepage/enabled),因为开启内存大页会到fork子进程的速度变慢,也会拖慢写操作的执行速度

redis的三大缓存问题

正常情况下,大部分的访问请求应该时先被redis缓存响应,在redis那里得不到响应的小部分访问请求才会去请求MySQL数据库获取数据,这样MySQL数据库的负载压力会非常小,能够正常稳定工作。

缓存雪崩/穿透/击穿问题的根本原因是在于redis缓存命中率下降,大量请求会直接发送给MySQL数据库,导致数据库负载压力过大而崩溃。

  1. 缓存雪崩:redis中大量不同的缓存key集中过期

  2. 缓存穿透:大量请求访问redis和MySQL数据库都不存在的数量

  3. 缓存击穿:redis中一个热点key过期,此时又有大量请求访问这个热点key

缓存雪崩解决方案
复制代码
使用随机数设置key的过期时间,防止集中过期
设置二级缓存
使用互斥锁,在查数据库时加锁,缓冲大量请求
缓存穿透解决方案
复制代码
使用布隆过滤器进行判断拦截一定不存在的无效请求
对空值数据也进行缓存
在业务层使用脚本等方式对用户的请求进行校验,排查非法请求
缓存击穿解决方案
复制代码
对热点缓存不设置过期时间
预先对热点数据进行缓存预热
使用互斥锁,在查数据库时加锁,缓冲大量请求

Redis 安装部署

reids软件包下载地址:https://download.redis.io/releases/

环境准备

复制代码
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
sed -i 's/enforcing/disabled/' /etc/selinux/config

#修改内核参数
vim /etc/sysctl.conf

vm.overcommit_memory = 1                     #内核允许超量使用内存直到用完为止,防止OOM杀死进程
net.core.somaxconn = 2048                    #指定处于监听状态的连接请求队列的最大长度

sysctl -p

具体流程

复制代码
安装redis
yum install -y gcc gcc-c++ make

tar zxvf /opt/redis-7.0.15.tar.gz -C /opt/
cd /opt/redis-7.0.15
make
make PREFIX=/usr/local/redis install
#由于Redis源码包中直接提供了 Makefile 文件,所以在解压完软件包后,不用先执行 ./configure 进行配置,可直接执行 make 与 make install 命令进行安装。

#创建redis工作目录
mkdir /usr/local/redis/{conf,log,data}

cp /opt/redis-7.0.15/redis.conf /usr/local/redis/conf/

useradd -M -s /sbin/nologin redis
chown -R redis.redis /usr/local/redis/

#环境变量
vim /etc/profile 
PATH=$PATH:/usr/local/redis/bin		#增加一行

source /etc/profile


//修改配置文件
vim /usr/local/redis/conf/redis.conf

bind 127.0.0.1 20.0.0.51					#87行,添加 监听的主机地址
protected-mode no					#111行,将本机访问保护模式设置no。如果开启了,那么在没有设定bind ip且没有设密码的情况下,Redis只允许接受本机的响应
port 6379										#138行,Redis默认的监听6379端口
daemonize yes									#309行,设置为守护进程,后台启动
pidfile /usr/local/redis/log/redis_6379.pid		#341行,指定 PID 文件
logfile "/usr/local/redis/log/redis_6379.log"	#354行,指定日志文件
dir /usr/local/redis/data						#504行,指定持久化文件所在目录
requirepass abc123								#1037行,增加一行,设置redis密码

//定义systemd服务管理脚本
vim /usr/lib/systemd/system/redis-server.service
[Unit]
Description=Redis Server
After=network.target

[Service]
User=redis
Group=redis
Type=forking
TimeoutSec=0
PIDFile=/usr/local/redis/log/redis_6379.pid
ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

#启动服务
systemctl start redis-server
systemctl enable redis-server

netstat -lntp | grep 6379

redis-cli -h 20.0.0.51 -p 6379 -a

Redis 命令工具

复制代码
redis-server:Redis 服务器启动命令
redis-benchmark:性能测试工具,用于检测 Redis 在本机的运行效率
redis-check-aof:修复有问题的 AOF 持久化文件
redis-check-rdb:修复有问题的 RDB 持久化文件
redis-cli:Redis 客户端命令行工具
redis-sentinel:Redis 哨兵集群使用

redis-cli 命令行工具

复制代码
语法:redis-cli -h host -p port [-a password]
-h :指定远程主机
-p :指定 Redis 服务的端口号
-a :指定密码,未设置数据库密码可以省略-a 选项
若不添加任何选项表示,则使用 127.0.0.1:6379 连接本机上的 Redis 数据库

redis-cli -h 192.168.80.10 -p 6379 -a 'abc123'  

redis-benchmark 测试工具

复制代码
redis-benchmark 是官方自带的 Redis 性能测试工具,可以有效的测试 Redis 服务的性能。
基本的测试语法:redis-benchmark [选项] [选项值]。
-h :指定服务器主机名。
-p :指定服务器端口。
-s :指定服务器 socket
-c :指定并发连接数。 
-n :指定请求数。
-d :以字节的形式指定 SET/GET 值的数据大小。
-k :1=keep alive 0=reconnect 。
-r :SET/GET/INCR 使用随机 key, SADD 使用随机值。
-P :通过管道传输<numreq>请求。
-q :强制退出 redis。仅显示 query/sec 值。
--csv :以 CSV 格式输出。
-l :生成循环,永久执行测试。
-t :仅运行以逗号分隔的测试命令列表。
-I :Idle 模式。仅打开 N 个 idle 连接并等待。

#向 IP 地址为 192.168.80.10、端口为 6379 的 Redis 服务器发送 100 个并发连接与 100000 个请求测试性能
redis-benchmark -h 192.168.80.10 -p 6379 -c 100 -n 100000

#测试存取大小为 100 字节的数据包的性能
redis-benchmark -h 192.168.80.10 -p 6379 -q -d 100

#测试本机上 Redis 服务在进行 set 与 lpush 操作时的性能
redis-benchmark -t set,lpush -n 100000 -q

Redis 数据库常用命令

string类型操作:(计数器)
复制代码
set 键 值
get 键
mset 键1 值1  键2 值2 ....
mget 键1 键2 ....
setex  键  秒  值            #创建键并设置过期时间
strlen 键                    #统计键值的字符长度
incr 键                      #数值递增+1
decr 键                      #数值递减-1
incrby 键 N                  #数值递增+N
decrby 键                    #数值递减-N
list类型操作:(消息队列)
复制代码
lpush 键 值1 值2 值3 ....             #从左边开始插入元素
rpush 键 值1 值2 值3 ....             #从右边开始插入元素
lrange 键 起始下标  起始下标          #查询指定范围的元素,起始位置 0表示从左边开始的第一个元素,终止位置 -1表示到最后一个元素
lpop 键 N                             #显示并删除从左边开始的N个元素
rpop 键 N                             #显示并删除从右边开始的N个元素
llen 键                               #统计元素的数量
lindex 键 元素下标                    #查看指定位置的元素值,元素位置的下标从左往右,从0开始
lset 键 元素下标  值                  #修改指定位置的元素值
lrem 键 N 元素值                      #从左边开始删除N个指定元素
linsert 键 before|after 元素 值       #在指定元素前|后插入一个新元素				      
hash类型操作:(存储对象,购物车)
复制代码
hset 键 字段 值
hmset 键 字段1 值1  字段2 值2  ....  
hget 键 字段 
hkeys 键                     #查看所有字段名
hvals 键                     #查看所有字段的值
hdel 键 字段                 #删除字段
set类型操作:(随机抽奖,求交集、差集、并集)
复制代码
sadd 键 值1 值2 ....         #元素值不能重复
smembers 键                  #查看元素,无序的
srem 键 值1 值2 ....         #删除指定的元素
srandmember 键 N             #随机显示N个元素
spop 键 N                    #随机显示N个元素并删除
scard 键                     #统计元素的数量
smove 键1 键2 值             #将键1的元素移动到键2中
sinter 键1 键2               #求键1和键2的交集
sdiff 键1 键2                #求键1和键2的差集
sunion 键1 键2               #求键1和键2的并集
zset类型操作:(排行榜,热搜)
复制代码
zadd 键 权重1 值1  权重2 值2  ....             #score权重是可以重复的,元素值不能重复
zrange 键  起始下标 起始下标 withscores        #根据元素下标查看元素,元素位置的下标从左往右,从0开始,-1为最后
zrangebyscore 键 起始权重  终止权重            #根据score从小到大的顺序查看元素
zrevrange 键  起始下标 起始下标 withscores     #降序查看元素
zrevrangebyscore 键  起始权重  终止权重        #按照score从大到小的顺序查看元素
zcard 键                                       #统计元素的数量
zcount 键 起始权重  终止权重                   #统计指定score范围的元素数量
zrem 键 值1 值2 ....                           #删除指定的元素
zincreby 键 权重 值                            #再指定score位置添加元素

del 键                        #删除键
type 键                       #查询键的数据类型
keys 键                       #查询键,支持通配符 * ?
exists 键                     #判断键是否存在,1表示存在,0表示不存在
expire 键 秒                  #为键设置过期时间
ttl 键                        #查询键的过期时间,-2表示已过期,-1表示永不过期
rename 键 新键                #重命名键,会覆盖已存在的键
renamenx 键 新键              #重命名键,不会覆盖已存在的键
dbsize                        #统计当前库中键的总数
select 库ID                   #切换库,默认库ID范围为 0~15
move 键 库ID                  #移动键到指定的库
flushdb                       #清空当前库中的键(慎用)
flushall                      #清空所有库的键(慎用)
修改密码
复制代码
config set requirepass '密码'    #修改redis密码
config get requirepass           #查询redis密码
相关推荐
卡布奇诺-海晨16 分钟前
MySQL的MVCC机制
数据库·mysql
hao_wujing42 分钟前
攻击模型的恶意行为检测
网络·数据库·php
秃头摸鱼侠2 小时前
MySQL查询语句(续)
数据库·mysql
MuYiLuck2 小时前
【redis实战篇】第八天
数据库·redis·缓存
睡觉待开机2 小时前
6. MySQL基本查询
数据库·mysql
�FENG2 小时前
Redis 安装配置和性能优化
redis·持久化
大熊猫侯佩3 小时前
由一个 SwiftData “诡异”运行时崩溃而引发的钩深索隐(三)
数据库·swiftui·swift
大熊猫侯佩3 小时前
由一个 SwiftData “诡异”运行时崩溃而引发的钩深索隐(二)
数据库·swiftui·swift
大熊猫侯佩3 小时前
用异步序列优雅的监听 SwiftData 2.0 中历史追踪记录(History Trace)的变化
数据库·swiftui·swift
大熊猫侯佩3 小时前
由一个 SwiftData “诡异”运行时崩溃而引发的钩深索隐(一)
数据库·swiftui·swift