💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
推荐:Linux运维老纪的首页,持续学习,不断总结,共同进步,活到老学到老
导航剑指大厂系列:全面总结 运维核心技术:系统基础、数据库、网路技术、系统安全、自动化运维、容器技术、监控工具、脚本编程、云服务等。
常用运维工具系列:常用的运维开发工具, zabbix、nagios、docker、k8s、puppet、ansible等
数据库系列:详细总结了常用数据库 mysql、Redis、MongoDB、oracle 技术点,以及工作中遇到的 mysql 问题等
懒人运维系列:总结好用的命令,解放双手不香吗?能用一个命令完成绝不用两个操作
数据结构与算法系列:总结数据结构和算法,不同类型针对性训练,提升编程思维,剑指大厂
非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨
NoSQL之Redis配置与优化(二)
一、redis与memcache总体对比
1.性能
- Redis:只使用单核,平均每一个核上Redis在存储小数据时比Memcached性能更高。
- Memcached:可以使用多核,而在100k以上的数据中,Memcached性能要高于Redis。
2.内存使用效率
- MemCached:使用简单的key-value存储,Memcached的内存利用率更高。
- Redis:如果采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。
3.内存空间和数据量大小
- MemCached:可以修改最大内存,采用LRU算法。Memcached单个key-value大小有限,一个value最大只支持1MB。
- Redis:增加了VM的特性,突破了物理内存的限制。Redis单个key-value大小最大支持512MB 。
4.数据结构支持
- MemCached:数据结构单一,仅用来缓存数据。
- Redis:支持更加丰富的数据类型,Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。可以在服务器端直接对数据进行丰富的操作,这样可以减少网络IO次数和数据体积。
5.可靠性
- Memcached:只是个内存缓存,对可靠性要求低。MemCached不支持数据持久化,断电或重启后数据消失,但稳定性是有保证的。
- Redis:对可靠性要求高,支持数据持久化和数据恢复,允许单点故障,同时也会影响部分性能。支持数据的备份,即master-slave模式的数据备份。Redis支持数据的持久化,可以将内存中的数据保存到磁盘中,重启的时候可以再次加载进行使用。
6.应用场景
- Memcached:动态系统中减轻数据库负载,提升性能;做缓存,适合多读少写,大数据量场景。
- Redis:适用于对读写效率要求都很高,数据处理业务复杂和对安全性要求较高的系统。
二、redis与memcache内存管理机制对比
1. Memcached的内存管理机制
Memcached默认使用Slab Allocation机制管理内存,其主要思想是按照预先规定的大小,将分配的内存分割成特定长度的块以存储相应长度的key-value数据记录,以完全解决内存碎片问题。Slab Allocation机制只为存储外部数据而设计,也就是说所有的key-value数据都存储在Slab Allocation系统里,而Memcached的其它内存请求则通过普通的malloc/free来申请,因为这些请求的数量和频率决定了它们不会对整个系统的性能造成影响
2. Redis的内存管理机制
Redis的内存管理主要通过源码中zmalloc.h和zmalloc.c两个文件来实现的。Redis为了方便内存的管理,在分配一块内存之后,会将这块内存的大小存入内存块的头部。如图 5所示,real_ptr是redis调用malloc后返回的指针。redis将内存块的大小size存入头部,size所占据的内存大小是已知的,为 size_t类型的长度,然后返回ret_ptr。当需要释放内存的时候,ret_ptr被传给内存管理程序。通过ret_ptr,程序可以很容易的算出 real_ptr的值,然后将real_ptr传给free释放内存。Redis采用的是包装的mallc/free,相较于Memcached的内存管理方法来说,要简单很多。
三、 Redis和Memcached的集群实现机制对比
1. Memcached的分布式存储
Memcached本身并不支持分布式,因此只能在客户端通过像一致性哈希这样的分布式算法来实现Memcached的分布式存储。
当客户端向Memcached集群发送数据之前,首先会通过内置的分布式算法计算出该条数据的目标节点,然后数据会直接发送到该节点上存储。但客户端查询数据时,同样要计算出查询数据所在的节点,然后直接向该节点发送查询请求以获取数据。
2. Redis的分布式存储
Redis在服务器端构建分布式存储。Redis Cluster是一个实现了分布式且允许单点故障的Redis高级版本,它没有中心节点,具有线性可伸缩的功能。其中节点与节点之间通过二进制协议进行通信,节点与客户端之间通过ascii协议进行通信。在数据的放置策略上,Redis Cluster将整个key的数值域分成4096个哈希槽,每个节点上可以存储一个或多个哈希槽,Redis Cluster支持的最大节点数就是4096。Redis Cluster使用的分布式算法:crc16( key ) % HASH_SLOTS_NUMBER。
为了保证单点故障下的数据可用性,Redis Cluster引入了Master节点和Slave节点。在Redis Cluster中,每个Master节点都会有对应的两个用于冗余的Slave节点。这样在整个集群中,任意两个节点的宕机都不会导致数据的不可用。当Master节点退出后,集群会自动选择一个Slave节点成为新的Master节点。
四、redis的安装
1.安装
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
[root@localhost ~]# yum -y install gcc* zlib-devel
[root@localhost ~]#tar xvzf redis-4.0.9.tar.gz
[root@localhost ~]#cd redis-4.0.9/
[root@localhost redis-4.0.9]# make
注意:
在make的时候,可能会出现如下错误提示:
- 解决方法1:用make MALLOC=libc指定内存分配器为进行编译
- 解决方法2:make clean && make distclean
[root@localhost redis-4.0.9]# make PREFIX=/usr/local/redis install
[root@localhost ~]# ln -s /usr/local/redis/bin/* /usr/local/bin/
[root@localhost redis-4.0.9]# cd /root/redis-4.0.9/utils/
[root@localhost utils]# ./install_server.sh
备注:
- Config file : /etc/redis/6379.conf //配置文件路径
- Log file : /var/log/redis_6379.log //日志文件路径
- Data dir : /var/lib/redis/6379 //数据文件路径
- Executable : /usr/local/redis/bin/redis-server //可执行文件路径
- Cli Executable : /usr/local/redis/bin/redis-cli //客户端命令行工具
2.查看进程
[root@localhost utils]# netstat -anpt | grep redis
3.服务控制
[root@localhost ~]#/etc/init.d/redis_6379 stop
[root@localhost ~]#/etc/init.d/redis_6379 start
[root@localhost ~]#/etc/init.d/redis_6379 restart
[root@localhost ~]#/etc/init.d/redis_6379 status
4.配置参数的修改
[root@localhost ~]#vim /etc/redis/6379.conf
bind 127.0.0.1192.168.10.101 //监听的主机地址
port 6379 //端口
daemonize yes //启用守护进程
pidfile /var/run/redis_6379.pid //指定 PID 文件
loglevel notice //日志级别
logfile /var/log/redis_6379.log //指定日志文件
[root@localhost~]#/etc/init.d/redis_6379 restart
[root@localhost utils]# netstat -anpt | grep redis
二、Redis 命令工具
- redis-server:用于启动 Redis 的工具;
- redis-benchmark:用于检测 Redis 在本机的运行效率;
- redis-check-aof:修复 AOF 持久化文件;
- redis-check-rdb:修复 RDB 持久化文件;
- redis-cli:Redis 命令行工具
1.redis-cli 命令行工具
(1)连接本机redis
[root@localhost ~]# redis-cli
127.0.0.1:6379>
(2)测试redis服务是否启动
127.0.0.1:6379> ping
PONG
(3)远程连接
[root@localhost ~]#redis-cli -h 192.168.10.101 -p 6379
2.获取帮助
- help @<group>:获取<group>中的命令列表;
- help <command>:获取某个命令的帮助;
- help <tab>:获取可能帮助的主题列表。
备注:
- help <tab>:获取可能帮助的主题列表。
输入help后,按下tab键
(1)查看所有与 List 数据类型的相关命令
127.0.0.1:6379>help @list
(2)查看 set 命令的命令帮助
127.0.0.1:6379>help set
3.redis-benchmark 测试工具
redis-benchmark 是官方自带的 Redis 性能测试工具,可以有效的测试 Redis 服务的性能。
- -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 连接并等待。
(1)测试请求性能
[root@localhost ~]#redis-benchmark -h 192.168.10.101 -p 6379 -c 100 -n 100000
备注:
- -h:指定服务器主机名;
- -p:指定服务器端口;
- -c:指定并发连接数;
- -n:指定请求数;
====== MSET (10 keys) ======
100000 requests completed in 1.02 seconds
100 parallel clients ##100个并发连接
3 bytes payload
keep alive: 1
87.25% <= 1 milliseconds ##87.25%的命令执行时间小于等于1毫秒
99.90% <= 2 milliseconds
100.00% <= 2 milliseconds
97943.19 requests per second #每秒的请求数
备注:
向 IP 地址为 192.168.10.101、端口为6379 的 Redis 服务器发送 100 个并发连接与100000 个请求测试性
(2)测试存取性能
[root@localhost ~]#redis-benchmark -h 192.168.10.101 -p 6379 -q -d 100
备注:
- -h:指定服务器主机名;
- -p:指定服务器端口;
- -d:以字节的形式指定 SET/GET 值的数据大小;
- -q:强制退出 redis。仅显示 query/sec 值;
PING_INLINE: 121506.68 requests per second
PING_BULK: 124378.11 requests per second
SET: 121654.50 requests per second
GET: 122100.12 requests per second
INCR: 118764.84 requests per second
LPUSH: 112612.61 requests per second
RPUSH: 118623.96 requests per second
LPOP: 107874.87 requests per second
RPOP: 114416.48 requests per second
SADD: 123304.56 requests per second
HSET: 122249.38 requests per second
SPOP: 128040.97 requests per second
LPUSH (needed to benchmark LRANGE): 116686.12 requests per second
LRANGE_100 (first 100 elements): 40016.00 requests per second
LRANGE_300 (first 300 elements): 11991.85 requests per second
LRANGE_500 (first 450 elements): 7381.71 requests per second
LRANGE_600 (first 600 elements): 5230.67 requests per second
MSET (10 keys): 92421.44 requests per second
备注:
测试存取大小为 100 字节的数据包的性能
- PING_INLINE:每秒完成多少次PING操作
- GET:每秒完成多少次GET key vlaue
- SET:每秒完成多少次SET key vlaue
- INCR:每秒完成多少次原子计数
- MSET:每秒多个key vlaue请求次数
(3)set 与 lpush 操作性能
[root@localhost ~]# redis-benchmark -t set,lpush -n 100000 -q
备注:
- -n:指定请求数;
- -q:强制退出 redis。仅显示 query/sec 值;
- -t:仅运行以逗号分隔的测试命令列表;
SET: 121951.22 requests per second
LPUSH: 127226.46 requests per second
备注:
测试本机上 Redis 服务在进行 set 与 lpush 操作时的性能。
Lpush 命令将一个或多个值插入到列表头部
三、Redis 数据库常用命令
- set:存放数据,基本的命令格式为set key value。
- get:获取数据,基本的命令格式为get key。
127.0.0.1:6379>set teacher zhanglong
127.0.0.1:6379>get teacher
1.key 相关命令
在Redis 数据库中,与key 相关的命令主要包含以下几种。
(1)添加键值对
使用keys 命令可以取符合规则的键值列表,通常情况可以结合*、?等选项来使用。
127.0.0.1:6379>set k1 1
OK
127.0.0.1:6379>set k2 2
OK
127.0.0.1:6379>set k3 3
OK
127.0.0.1:6379>set v1 4
OK
127.0.0.1:6379>set v5 5
OK
(2)查看当前数据库中所有键
127.0.0.1:6379>KEYS *
1) "teacher"
2) "k1"
3) "k2"
4) "k3"
5) "v1"
6) "v5"
127.0.0.1:6379>set v22 5
O
(3)查看当前数据库中以v 开头的数据
127.0.0.1:6379>KEYS v*
1) "v1"
2) "v5"
3) "v22"
(4)查看当前数据库中以v 开头后面包含任意一位的数据
127.0.0.1:6379>KEYS v?
1) "v1"
2) "v5"
(5)查看当前数据库中以v 开头v 开头后面包含任意两位的数据
127.0.0.1:6379>KEYS v??
1) "v22"
2.exists
exists 命令可以判断键值是否存在
127.0.0.1:6379>exists teacher
(integer) 1
结果为1,表示 teacher 键是存在
127.0.0.1:6379>exists tea
(integer) 0
结果为0,表示 tea 键不存在
3.del
del 命令可以删除当前数据库的指定key
127.0.0.1:6379>keys *
1) "teacher"
2) "v1"
3) "v22"
4) "k3"
5) "k1"
6) "k2"
7) "v5"
127.0.0.1:6379> del v5
(integer) 1
127.0.0.1:6379>get v5
(nil)
4.type
使用type 命令可以获取key 对应的value 值类型
127.0.0.1:6379>type k1
string
备注:
redis支持的数据类型
- String:最简单的类型,就是普通的set和get,作key value缓存。
- Hash:类似map的一种结构,一般就是可以将结构化的数据,比如一个对象给缓存在redis里
- List:List是有序列表,可以通过list存储一些列表型的数据结构,类似粉丝列表、文章的评论列表之类的东西
- Set:Set是无序集合,自动去重。
- Sorted Set:Sorted Set是排序的set,去重但可以排序,写进去的时候给一个分数,自动根据分数排序。
5.rename
rename 命令是对已有key 进行重命名
在实际使用过程中,建议先用exists 命令查看目标key 是否存在,然后再决定是否执行rename 命令,以避免覆盖重要数据
127.0.0.1:6379>keys v*
1) "v1"
2) "v22"
127.0.0.1:6379>rename v22 v2
OK
127.0.0.1:6379>keys v*
1) "v1"
2) "v2"
127.0.0.1:6379>get v1
"4"
127.0.0.1:6379>get v2
"5"
127.0.0.1:6379>rename v1 v2
OK
127.0.0.1:6379>get v1
(nil)
127.0.0.1:6379>get v2
"4"
6.renamenx
renamenx 命令的作用是对已有key 进行重命名,并检测新名是否存在。
使用renamenx 命令进行重命名时,如果目标key 存在则不进行重命名。
127.0.0.1:6379>keys *
1) "teacher"
2) "k3"
3) "k1"
4) "k2"
5) "v2"
127.0.0.1:6379>get teacher
"zhanglong"
127.0.0.1:6379>get v2
"4"
127.0.0.1:6379>renamenx v2 teacher
(integer) 0
127.0.0.1:6379>keys *
1) "teacher"
2) "k3"
3) "k1"
4) "k2"
5) "v2"
127.0.0.1:6379>get teacher
"zhanglong"
127.0.0.1:6379>get v2
"4
7.dbsize
dbsize 命令的作用是查看当前数据库中key 的数目。
127.0.0.1:6379> dbsize
(integer) 5
四、多数据库常用命令
1.多数据库间切换
Redis 在没有任何改动的情况下默认包含16 个数据库,数据库名称是用数字0-15 来依次命名的
(1)切换至序号为10 的数据库
127.0.0.1:6379>select 10
OK
(2)切换至序号为15 的数据库
127.0.0.1:6379[10]>select 15
OK
(3)切换至序号为0 的数据库
127.0.0.1:6379[15]>select 0
2.多数据库间移动数据
Redis 的多数据库在一定程度上是相对独立的,例如在数据库0 上面存放k1 的数据,在其它1-15 的数据库上是无法查看到的。
127.0.0.1:6379>set k1 100
OK
127.0.0.1:6379>get k1
"100"
127.0.0.1:6379>select 1
OK
127.0.0.1:6379[1]>get k1
(nil)
127.0.0.1:6379[1]>select 0 //切换至目标数据库0
OK
127.0.0.1:6379>get k1 //查看目标数据是否存在
"100"
127.0.0.1:6379>move k1 1 //将数据库0 中k1 移动到数据库1 中
(integer) 1
127.0.0.1:6379>select 1 //切换至目标数据库1
OK
127.0.0.1:6379[1]>get k1 //查看被移动数据
"100"
127.0.0.1:6379[1]> select 0
OK
127.0.0.1:6379> get k1 //在数据库0 中无法查看到k1 的值
(nil)
3.清除数据库内数据
清空当前数据库数据,使用FLUSHDB
命令实现;清空所有数据库的数据,使用FLUSHALL 命令实现
五、Redis 持久化
Redis 的所有数据都是保存在内存中,然后不定期的通过异步方式保存到磁盘上(这称为“半持久化模式”);也可以把每一次数据变化都写入到一个append only file(aof)里面(这称为“全持久化模式”)。
由于Redis 的数据都存放在内存中,如果没有配置持久化,Redis 重启后数据就全丢失了。所以,需要开启Redis 的持久化功能,将数据保存到磁盘上,当Redis 重启后,可以从磁盘中恢复数据。Redis 提供两种方式进行持久化,一种是RDB(Redis DataBase) 持久化(原理是将Reids在内存中的数据库记录定时dump 到磁盘上的RDB 持久化),另外一种是AOF(append only file)持久化(原理是将Reids 的操作日志以追加的方式写入文件)。
1.RDB 和AOF 的区别
(1)RDB是什么?
默认采用的方法
RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发。
触发机制:手动触发分别对应为save和bgsave命令
- save命令:阻塞当前Redis服务器,直到RDB过程完成为止,对于内存比较多的实例会造成时间阻塞。线上环境不建议使用。
- bgsave命令:Redis进程执行fork(用于创建进程的函数)操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段。
(2)RDB的优缺点:
RDB的优点:
RDB是一个紧凑压缩的二进制文件,代表Redis在某一个时间点上的数据快照。非常适用于备份,全量复制等场景。比如每6小时执行bgsave备份,并把RDB文件拷贝到远程机器或者文件系统中,用于灾难恢复。
Redis加载RDB恢复数据远远快于AOF方式。
RDB的缺点:
RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都有执行fork操作创建子进程,属于重量级操作,频繁执行成本过高。
RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,存在老版本Redis服务无法兼容新版RDB格式的问题。
2.AOF是什么
AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中命令达到恢复数据的目的。AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流
二者选择的标准:
牺牲一些性能,换取更高的缓存一致性(AOF),
写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save 的时候,再做备份(RDB)
备注:
如果redies重启之后,需要加载一个持久化文件,有限会选择AOF文件。
如果先开启了RDB,再开启AOF,RDB先执行了持久化,那么RDB文件中的内容会被AOF覆盖掉。
3.Redis 持久化配置
(1)RDB 持久化配置
[root@localhost ~]# vim /etc/redis/6379.conf
打开6379.conf 文件之后,搜索save,可以看到如下所示配置信息。
- save 900 1:在900 秒(15 分钟)之后,如果至少有1 个key 发生变化,则dump内存快照。
- save 300 10:在300 秒(5 分钟)之后,如果至少有10 个key 发生变化,则dump内存快照。
- save 60 10000:在60 秒(1 分钟)之后,如果至少有10000 个key 发生变化,则dump 内存快照。
- dbfilename dump.rdb:RDB文件名称 ##254行
- dir /var/lib/redis/6379:RDB文件路径 ##264行
- rdbcompression yes:是否进行压缩 ##242行
(2)AOF 持久化配置
在Redis 的配置文件中存在三种同步方式,它们分别是:
- appendonly yes:开启AOF持久化(默认为no) ##673行
- appendfilename "appendonly.aof ":AOF文件名称 ##677行
- # appendfsync always
- appendfsync everysec
- # appendfsync no
- always:同步持久化,每次发生数据变化会立刻写入磁盘
- everysec:默认推荐,每秒异步记录一次(默认值)
- no:不同步,交给操作系统决定如何同步
- aof-load-truncated yes ##769行
忽略最后一条可能存在问题的指令
[root@localhost ~]#/etc/init.d/redis_6379 restart
(3)AOF重写
为了解决AOF 文件体积不断增大的问题,用户可以向Redis 发送BGREWRITEAOF命令。BGREWRITEAOF 命令会通过移除AOF 文件中的冗余命令来重写(rewrite)AOF文件,使AOF 文件的体积尽可能地变小。
127.0.0.1:6379> bgrewriteaof
Background append only file rewriting started
# 在日志进行BGREWRITEAOF时,如果no-appendfsync-on-rewrite设置为yes表示新写操作不进行同步fsync,只是暂存在缓冲区里,避免造成磁盘IO操作冲突,等重写完成后再写入。Redis中默认为no
no-appendfsync-on-rewrite no
#当前AOF文件大小是上次日志重写时AOF文件大小两倍时,发生BGREWRITEAOF操作
auto-aof-rewrite-percentage 100
备注:
100指的是aof文件增长比例,指当前aof文件比上次重写的增长比例大小,100为两倍
#当前AOF文件执行BGREWRITEAOF命令的最小值,避免刚开始启动Reids时由于文件尺寸较小导致频繁的BGREWRITEAOF
auto-aof-rewrite-min-size 64mb
六、性能管理
1.查看内存信息
192.168.9.236:7001> info memory
used_memory:1210776 #已经内存使用的大小,以字节为单位
used_memory_human:1.15M # 带单位展示,以M为单位
used_memory_rss:7802880 # 从操作系统角度看redis内存占用多少
used_memory_rss_human:7.44M # 带单位展示
maxmemory:1073741824 # 最大内存大小
maxmemory_human:1.00G # 带单位展示
2.回收策略
maxmemory-policy:回收策略
- volatile-lru:它允许Redis 从整个数据集中挑选最近最少使用的key 进行删除
- volatile-ttl:按照key的过期时间进行淘汰
- volatile-random:从已设置过期时间的数据集合中随机挑选数据淘汰;
- allkeys-lru:使用LRU 算法从所有数据集合中淘汰数据;
- allkeys-random:从数据集合中任意选择数据淘汰;
- noeviction:禁止淘汰数据(默认值)
备注:
设置key的过期时间
expire v1 10
v1的过期时间为10秒
备注:
当Redis 由于内存压力需要回收一个key 时,Redis 首先考虑的不是回收最旧的数据,而是在最近最少使用的key 或即将过期的key 中随机选择一个key,从数据集中删除
七、redis设置密码
1.设置方法
方法一:通过配置文件redis.conf设置密码
找到requirepass关键字,后面就是跟的密码,默认情况下是注释掉的,即默认不需要密码
打开注释,设置为自己的密码,重启即可
方法二:通过命名设置密码
使用redis-cli连接上redis,执行如下命令
config set requirepass 123456
执行完毕,无需重启,退出客户端,重新登录就需要输入密码了
2.连接方法
(1)连接时输入密码
[root@localhost bin]# ./redis-cli -a 123456
(2)先连接再输入密码
[root@localhost bin]# ./redis-cli127.0.0.1:6379> auth 123456
3.关闭方法
[root@localhost bin]# ./redis-cli -a 123456 shutdown
4.区别
- 修改配置文件设置的密码永久生效;使用命令设置的密码临时生效,重启后失效
- 修改配置文件设置的密码,需要重启生效;使用命令设置的密码,退出后再登录生效,重启后失效
- 命令的优先级高于配置文件的优先级