NoSQL之 Redis配置与优化

时间:2024-11-04 16:53:06

文章目录

  • NoSQL之 Redis配置与优化
    • 数据库类型
      • 关系型数据库
      • 非关系型数据库
      • 关系型数据库SQL 和 非关系型数据库NoSQL 的区别?
    • Redis
      • Redis为什么那么快?
      • Redis工具
      • redis持久化
      • redis性能优化
      • redis的三大缓存问题
        • 缓存雪崩解决方案
        • 缓存穿透解决方案
        • 缓存击穿解决方案
    • Redis 安装部署
      • 环境准备
      • 具体流程
      • Redis 命令工具
      • redis-cli 命令行工具
      • redis-benchmark 测试工具
      • Redis 数据库常用命令
        • string类型操作:(计数器)
        • list类型操作:(消息队列)
        • hash类型操作:(存储对象,购物车)
        • set类型操作:(随机抽奖,求交集、差集、并集)
        • zset类型操作:(排行榜,热搜)
        • 修改密码

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密码