Redis是一种NOSQL数据库(非关系型数据库) ,也是NOSQL中key-value存储的代表,不关心value的格式。与传统数据库不同的是redis的数据是存在内存中,读写速度非常快,所以redis被广泛应用于缓存方向,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。另外,Redis 也经常用来做分布式锁。除此之外,Redis 支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。
Redis提供的API语言包括C、C++、C#、Java、JavaScript、Lua、Objective-C、Perl、PHP、Python、Ruby、Go、Tcl等。
1.2.1 优点
1) 读写性能优异, Redis能读的速度是次/s,写的速度是81000次/s。
2) 支持数据持久化,支持AOF和RDB两种持久化方式。
3) 支持事务,Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。
4) 数据结构丰富,除了支持string类型的value外还支持hash、set、zset、list等数据结构。
5) 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。
1.2.2 缺点
1) 数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
2) Redis 不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的IP才能恢复。
3) 主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性。
4) Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。为避免这一问题,运维人员在系统上线时必须确保有足够的空间,这对资源造成了很大的浪费。
5) 不适合缓存大尺寸的对象
1) 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度都是O(1);
2) 数据结构简单,对数据操作也简单,Redis 中的数据结构是专门进行设计的;
3) 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
配置详解:https://www.cnblogs.com/kreo/p/4423362.html
1: Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程
daemonize no
2: 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
pidfile /var/run/redis.pid
3: 指定Redis监听端口,默认端口为6379,作者在自己的一篇博文中解释了为什么选用6379作为默认端口,
因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字
port 6379
4: 绑定的主机地址
bind 127.0.0.1
5: 当 客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
timeout 300
6: 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,
默认为verbose
loglevel verbose
7: 日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志
记录方式为标准输出,则日志将会发送给/dev/null
logfile stdout
8: 设置数据库的数量,默认数据库为0,可以使用SELECT <dbid>命令在连接上指定数据库id
databases 16
9: 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
save <seconds> <changes>
Redis默认配置文件中提供了三个条件:
save 900 1
save 300 10
save 60 10000
分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。
10: 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,
可以关闭该选项,但会导致数据库文件变的巨大
rdbcompression yes
11: 指定本地数据库文件名,默认值为dump.rdb
dbfilename dump.rdb
12: 指定本地数据库存放目录
dir https://blog.csdn.net/liyue/article/details/
13: 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
slaveof <masterip> <masterport>
14: 当master服务设置了密码保护时,slav服务连接master的密码
masterauth <master-password>
15: 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH <password>命令提供密码,默认关闭
requirepass foobared
16: 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,
如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端
返回max number of clients reached错误信息
maxclients 128
17: 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,
当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,
Value会存放在swap区
maxmemory <bytes>
18: 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。
因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no
appendonly no
19: 指定更新日志文件名,默认为appendonly.aof
appendfilename appendonly.aof
20: 指定更新日志条件,共有3个可选值:
no:表示等操作系统进行数据缓存同步到磁盘(快)
always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
everysec:表示每秒同步一次(折衷,默认值)
appendfsync everysec
21: 指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,
访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制)
vm-enabled no
22: 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享
vm-swap-file /tmp/redis.swap
23: 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),
也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0
vm-max-memory 0
24: Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,
vm-page-size是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;
如果存储很大大对象,则可以使用更大的page,如果不 确定,就使用默认值
vm-page-size 32
25: 设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。
vm-pages
26: 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,
可能会造成比较长时间的延迟。默认值为4
vm-max-threads 4
27: 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启
glueoutputbuf yes
28: 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法
hash-max-zipmap-entries 64
hash-max-zipmap-value 512
29: 指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍)
activerehashing yes
30: 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件
include /path/to/local.conf
数据类型
数据类型存储的值
说 明
STRING(字符串)
可以是保存字符串、整数和浮点数
可以对字符串进行操作,比如增加字符或者求子串:如果是整数或者浮点数,可以实现计算,比如自增等
LIST(列表)
它是一个链表,它的每一个节点都包含一个字符串
Redis 支持从链表的两端插入或者弹出节点,或者通过偏移对它进行裁剪;还可以读取一个或者多个节点,根据条件删除或者查找节点等
SET(集合)
它是一个收集器,但是是无序的,在它里而每一个元素都是一个字符串,而且是独一无二,各不相同的
可以新增、读取、删除单个元素:检测一个元素是否在集合中;计算它和其他集合的交集、并集和差集等;随机从集合中读取元素
HASH(哈希散列表)
它类似于 Java 语言中的 Map,是一个键值对应的无序列表
可以増、删、査、改单个键值对,也可以获取所有的键值对
ZSET(有序集合)
它是一个有序的集合,可以包含字符 串、整数、浮点数、分值(score),元素 的排序是依据分值的大小来决定的
可以增、删、査、改元素,根据分值的范围或者成员 來获取对应的元索
HyperLogLog(基数)
它的作用是计算重复的值,以确定存储的数量
只提供基数的运算,不提供返回的功能
redis的数据都存储在内存中,如果存储的数据长时间不适用会占用内存空间,并且在持久化或者主从同步时对redis造成影响。redis提供key的过期删除策略和内存的淘汰策略
2.3.1 设置key的过期时间
Redis提供了四个命令来设置过期时间(生存时间)。
(1) EXPIRE <key> <ttl> :表示将键 key 的生存时间设置为 ttl 秒。
(2) PEXPIRE <key> <ttl> :表示将键 key 的生存时间设置为 ttl 毫秒。
(3) EXPIREAT <key> <timestamp> :表示将键 key 的生存时间设置为 timestamp 所指定的秒数时间戳。
(4) PEXPIREAT <key> <timestamp> :表示将键 key 的生存时间设置为 timestamp 所指定的毫秒数时间戳
前面三种设置的过期时间最后存储的时候都会转换成第四种
2.3.1.1 移除键的过期时间
PERSIST <key> :表示将key的过期时间移除。
2.3.1.2 返回键的剩余生存时间
TTL <key> :以秒的单位返回键 key 的剩余生存时间。
PTTL <key> :以毫秒的单位返回键 key 的剩余生存时间。
2.3.2 过期时间的判定
在Redis内部,每当我们设置一个键的过期时间时,Redis就会将该键带上过期时间存放到一个过期字典中。当我们查询一个键时,Redis便首先检查该键是否存在过期字典中,如果存在,那就获取其过期时间。然后将过期时间和当前系统时间进行比对,比系统时间大,那就没有过期;反之判定该键过期。
2.3.3 过期删除策略
2.3.3.1 定时删除
在设置某个key 的过期时间同时,我们创建一个定时器,让定时器在该过期时间到来时,立即执行对其进行删除的操作。
优点:定时删除对内存是最友好的,能够保存内存的key一旦过期就能立即从内存中删除。
缺点:对CPU最不友好,在过期键比较多的时候,删除过期键会占用一部分 CPU 时间,对服务器的响应时间和吞吐量造成影响。
2.3.3.2 惰性删除
设置该key 过期时间后,我们不去管它,当需要该key时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key。
优点:对 CPU友好,我们只会在使用该键时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查。
缺点:对内存不友好,如果一个键已经过期,但是一直没有使用,那么该键就会一直存在内存中,如果数据库中有很多这种使用不到的过期键,这些键便永远不会被删除,内存永远不会释放。从而造成内存泄漏。
2.3.3.3 定期删除
每隔一段时间,我们就对一些key进行检查,删除里面过期的key。
优点:可以通过限制删除操作执行的时长和频率来减少删除操作对 CPU 的影响。另外定期删除,也能有效释放过期键占用的内存。
缺点:难以确定删除操作执行的时长和频率。1、执行的太频繁,定期删除策略变得和定时删除策略一样,对CPU不友好;2、执行的太少,那又和惰性删除一样了,过期键占用的内存不会及时得到释放。如果在获取某个键时,如果某个键的过期时间已经到了,但是还没执行定期删除,那么就会返回这个键的值,这是业务不能忍受的错误。
2.3.4 Redis实际的删除策略
Redis的过期删除策略就是:惰性删除和定期删除两种策略配合使用(不需要配置)
惰性删除:Redis的惰性删除策略由 db.c/expireIfNeeded 函数实现,所有键读写命令执行之前都会调用 expireIfNeeded 函数对其进行检查,如果过期,则删除该键,然后执行键不存在的操作;未过期则不作操作,继续执行原有的命令。
定期删除:由redis.c/activeExpireCycle 函数实现,函数以一定的频率运行,每次运行时,都从一定数量的数据库中取出一定数量的随机键进行检查,并删除其中的过期键。
定期删除函数的运行频率,在Redis2.6版本中,规定每秒运行10次,大概100ms运行一次。在Redis2.8版本后,可以通过修改配置文件redis.conf 的 hz 选项来调整这个次数。Hz参数不建议设置太大,会对cpu造成压力
2.3.5 内存淘汰策略
通过过期删除策略,对于某些永远使用不到的键,并且多次定期删除也没选定到并删除,那么这些键同样会一直驻留在内存中,又或者在Redis中存入了大量的键,这些操作可能会导致Redis内存不够用,此时需要使用Redis的内存淘汰策略
2.3.5.1 设置Redis最大内存
在配置文件redis.conf 中,可以通过参数 maxmemory <bytes> 来设定最大内存。不设定该参数默认是无限制的,但是通常会设定其为物理内存的四分之三
2.3.5.2 设置内存淘汰方式
当现有内存大于maxmemory 时,便会触发redis主动淘汰内存方式,通过设置 maxmemory-policy ,有如下几种淘汰方式:
1)volatile-lru 利用LRU算法移除设置过过期时间的key (LRU:最近使用 Least Recently Used ) 。
2)allkeys-lru 利用LRU算法移除任何key (和上一个相比,删除的key包括设置过期时间和不设置过期时间的)。通常使用该方式。
3)volatile-random 移除设置过过期时间的随机key 。
4)allkeys-random 无差别的随机移除。
5)volatile-ttl 移除即将过期的key(minor TTL)
6)noeviction 不移除任何key,只是返回一个写错误 ,默认选项,一般不会选用。
requirepass作用:对登录权限做限制,redis每个节点的requirepass可以是独立、不同的。
masterauth作用:主要是针对master对应的slave节点设置的,在slave节点数据同步的时候用到。
CONFIG SET masterauth
CONFIG SET requirepass
CONFIG rewrite
redis是内存数据库,它把数据存储在内存中。为了数据的安全需要做持久化。Redis提供两种持久化功能:RDB和AOF
1) RDB(Redis DataBase)持久化:原理是将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化
2) AOF(Append Only File)持久化:原理是将Reids的操作日志以追加的方式写入文件
3.1.1 工作流程
Redis服务器接收到触发信息,将全量的redis内存数据写入到磁盘中
3.1.2 触发方式
触发rdb持久化的方式有三种,分别是手动触发、自动触发和其他方式
3.1.2.1 手动触发
后台手动执行save或者bgsave命令。
1) save:当客户端向服务器发送save命令请求进行持久化时,服务器会阻塞save命令之后的其他客户端的请求,直到数据同步完成。如果数据量太大,同步数据会执行很久,而这期间Redis服务器也无法接收其他请求,所以,最好不要在生产环境使用save命令
2) bgsave:bgsave命令是一个异步操作。当客户端向服务器发出bgsave命令时,Redis服务器主进程会forks一个子进程来同步全量数据,会将全量数据,在将数据保存到rdb文件之后,子进程会退出。与save命令相比,Redis服务器在处理bgsave采用子线程进行IO写入,而主进程仍然可以接收其他请求,但forks子进程是同步的,所以forks子进程时,一样不能接收其他请求,这意味着,如果forks一个子进程花费的时间太久(一般是很快的),bgsave命令仍然有阻塞其他客户的请求的情况发生
bgsave时COW(copy on write)机制
Redis在持久化的时候会去调用glibc的函数fork出一个子进程,快照持久化完成交由子进程来处理,父进程继续响应客户端的请求。而在子进程刚刚产生时,它其实使用的是父进程中的代码段和数据段。所以fork之后,kernel会将父进程中所有的内存页的权限都设置为read-only,然后子进程的地址空间指向父进程的地址空间。当父进程写内存时,CPU硬件检测到内存页是read-only的,就会触发页异常中断(page-fault),陷入 kernel 的一个中断例程。中断例程中,kernel就会把触发的异常的页复制一份,于是父子进程各自持有独立的一份。而此时子进程相应的数据还是没有发生变化,依旧是进程产生时那一瞬间的数据,故而子进程可以安心地遍历数据,进行序列化写入磁盘了。
随着父进程修改操作的持续进行,越来越多的共享页面将会被分离出来,内存就会持续增长,但是也不会超过原有数据内存的两倍大小,fork一个子进程,只有在父进程发生写操作修改内存数据时,才会真正去分配内存空间,并复制内存数据,而且也只是复制被修改的内存页中的数据,并不是全部内存数据;
命令
save
bgsave
IO类型
同步
异步
阻塞
是
是(阻塞发生在fock(),通常非常快)
优点
不会消耗额外的内存
不阻塞客户端命令
缺点
阻塞客户端命令
需要fock子进程,消耗内存
3.1.2.2 自动触发
通过配置文件对 Redis 进行设置,在不同维度下自动实现RDB持久化
相关配置如下:
# RDB自动持久化规则
# 当 900 秒内有至少有 1 个键被改动时,自动进行数据集保存操作
save 900 1
# 当 300 秒内有至少有 10 个键被改动时,自动进行数据集保存操作
save 300 10
# 当 60 秒内有至少有 10000 个键被改动时,自动进行数据集保存操作
save 60 10000
#不开启RDB持久化
save “ ”
# RDB持久化文件名
dbfilename dump-<port>.rdb
# 数据持久化文件存储目录
dir /var/lib/redis
# bgsave发生错误时是否停止写入,通常为yes
stop-writes-on-bgsave-error yes
# rdb文件是否使用压缩格式
rdbcompression yes
# 是否对rdb文件进行校验和检验,通常为yes
rdbchecksum yes
3.1.2.3 其他触发方式
1) 自动触发:每次关闭redis也会自动触发RDB
2) 自动触发:执行flushall命令也会自动触发RDB
3) 主从同步
3.1.3 优缺点
RDB的优点
4) 与AOF方式相比,通过rdb文件恢复数据比较快。
5) rdb文件非常紧凑,适合于数据备份。
6) 通过RDB进行数据备,由于使用子进程生成,所以对Redis服务器性能影响较小。
RDB的缺点
7) 如果服务器宕机的话,采用RDB的方式会造成某个时段内数据的丢失,比如我们设置10分钟同步一次或5分钟达到1000次写入就同步一次,那么如果还没达到触发条件服务器就死机了,那么这个时间段的数据会丢失。
8) 使用save命令会造成服务器阻塞,直接数据同步完成才能接收后续请求。
9) 使用bgsave命令在forks子进程时,如果数据量太大,forks的过程也会发生阻塞,另外,forks子进程会耗费内存。
3.2.1 工作流程
AOF是通过保存对redis服务端的写命令(如set、sadd、rpush)来记录数据库状态的,即保存你对redis数据库的写操作,写操作以Redis协议追加保存到以后缀为aof文件末尾,在Redis服务器重启时,会加载并运行aof文件的命令,以达到恢复数据的目的
3.2.2 触发方式
通过配置aof的配置来实现
相关配置:
#AOF文件存放目录
dir "/data/dbs/redis/6381"
#开启AOF持久化,默认关闭
appendonly yes
#AOF文件名称(默认)
appendfilename "appendonly.aof"
#AOF持久化策略(选择一种)
appendfsync always
appendfsync everysec
appendfsync no
#触发AOF文件重写的条件(默认
auto-aof-rewrite-percentage 100
#触发AOF文件重写的条件(默认
auto-aof-rewrite-min-size 64mb
AOF的持久化是通过命令追加、文件写入和文件同步三个步骤实现的。当reids开启AOF后,服务端每执行一次写操作(如set、sadd、rpush)就会把该条命令追加到一个单独的AOF缓冲区的末尾,这就是命令追加;然后把AOF缓冲区的内容写入AOF文件里。看上去第二步就已经完成AOF持久化了那第三步是干什么的呢?这就需要从系统的文件写入机制说起:一般我们现在所使用的操作系统,为了提高文件的写入效率,都会有一个写入策略,即当你往硬盘写入数据时,操作系统不是实时的将数据写入硬盘,而是先把数据暂时的保存在一个内存缓冲区里,等到这个内存缓冲区的空间被填满或者是超过了设定的时限后才会真正的把缓冲区内的数据写入硬盘中。也就是说当redis进行到第二步文件写入的时候,从用户的角度看是已经把AOF缓冲区里的数据写入到AOF文件了,但对系统而言只不过是把AOF缓冲区的内容放到了另一个内存缓冲区里而已,之后redis还需要进行文件同步把该内存缓冲区里的数据真正写入硬盘上才算是完成了一次持久化。
何时进行文件同步则是根据配置的appendfsync来进行:
appendfsync有三个选项:always、everysec和no
1、选择always的时候服务器会在每执行一个事件就把AOF缓冲区的内容强制性的写入硬盘上的AOF文件里,可以看成你每执行一个redis写入命令就往AOF文件里记录这条命令,这保证了数据持久化的完整性,但效率是最慢的,却也是最安全的;
2、配置成everysec的话服务端每执行一次写操作(如set、sadd、rpush)也会把该条命令追加到一个单独的AOF缓冲区的末尾,并将AOF缓冲区写入AOF文件,然后每隔一秒才会进行一次文件同步把内存缓冲区里的AOF缓存数据真正写入AOF文件里,这个模式兼顾了效率的同时也保证了数据的完整性,即使在服务器宕机也只会丢失一秒内对redis数据库做的修改;
3、将appendfsync配置成no则意味redis数据库里的数据就算丢失你也可以接受,它也会把每条写命令追加到AOF缓冲区的末尾,然后写入文件,但什么时候进行文件同步真正把数据写入AOF文件里则由系统自身决定,即当内存缓冲区的空间被填满或者是超过了设定的时限后系统自动同步。这种模式下效率是最快的,但对数据来说也是最不安全的,如果redis里的数据都是从后台数据库如mysql中取出来的,属于随时可以找回或者不重要的数据,那么可以考虑设置成这种模式。
3.2.3 AOF重写
随着Redis的运行,AOF的日志会越来越长,如果实例宕机重启,那么重放整个AOF将会变得十分耗时,而在日志记录中,又有很多无意义的记录,比如我现在将一个数据incr 一千次,那么就不需要去记录这1000次修改,只需要记录最后的值即可。所以就需要进行 AOF 重写。
Redis 提供了bgrewriteaof指令用于对AOF日志进行重写,该指令运行时会开辟一个子进程对内存进行遍历,然后将其转换为一系列的 Redis 的操作指令,再序列化到一个日志文件中。完成后再替换原有的AOF文件,至此完成。
也支持在redis.config中对重写机制的触发进行配置:通过将no-appendfsync-on-rewrite设置为yes,开启重写机制
重写相关配置:
配置名
含义
no-appendfsync-on-rewrite
是否开启重写。默认为no
auto-aof-rewrite-min-size
触发AOF文件执行重写的最小尺寸。默认64M
auto-aof-rewrite-percentage
触发AOF文件执行重写的增长率。默认100
当AOF文件的体积大于64Mb,并且AOF文件的体积比上一次重写之久的体积大了至少一倍(100%)时,Redis将执行 bgrewriteaof 命令进行重写。
3.2.4 优缺点
AOF的优点
1) AOF只是追加日志文件,因此对服务器性能影响较小,速度比RDB要快,消耗的内存较少。
AOF的缺点
1) AOF方式生成的日志文件太大,即使通过AFO重写,文件体积仍然很大。
2) 恢复数据的速度比RDB慢。
同时结合RDB持久化以及AOF持久化混合写入AOF文件。这样做的好处是可以结合rdb和aof的优点, 快速加载同时避免丢失过多的数据,缺点是aof里面的rdb部分就是压缩格式不再是aof格式,可读性差
3.3.1 配置
通过aof-use-rdb-preamble配置参数控制,yes则表示开启,no表示禁用,默认是禁用的,可通过config set修改
3.3.2 持久化
混合持久化同样也是通过bgrewriteaof完成的,不同的是当开启混合持久化时,fork出的子进程先将共享的内存副本全量的以RDB方式写入aof文件,然后在将重写缓冲区的增量命令以AOF方式写入到文件,写入完成后通知主进程更新统计信息,并将新的含有RDB格式和AOF格式的AOF文件替换旧的的AOF文件。简单的说:新的AOF文件前半段是RDB格式的全量数据后半段是AOF
3.3.3 恢复
当我们开启了混合持久化时,启动redis依然优先加载aof文件,aof文件加载可能有两种情况如下:
1) aof文件开头是rdb的格式, 先加载 rdb内容再加载剩余的 aof。
2) aof文件开头不是rdb的格式,直接以aof格式加载整个文件。
redis的部署方式分为单机模式、集群模式、主从模式、哨兵模式
这也是最基本的部署方式,只需要一台机器,负责读写,一般只用于开发人员自己测试
在主从模式中将数据库分为两类:主数据库(master)、从数据库(slave)。主数据库会负责整个系统中的读写操作,从数据库会负责我们整个数据库中的读操作。在现场环境中主数据库只负责写操作,让从数据库只负责读操作,就是为了读写分离,减轻服务器的压力。一个master可以有多个slave,但一个slave只能有一个master
主要使用场景数据量比较固定的环境,不需要扩容。
4.2.1 主从同步流程
(1)从数据库启动成功后,连接主数据库,发送 SYNC 命令;
(2)主数据库接收到 SYNC 命令后,开始执行 BGSAVE 命令生成 RDB 文件并使用缓冲区记录此后执行的所有写命令;
(3)主数据库 BGSAVE 执行完后,向所有从数据库发送快照文件,并在发送期间继续记录被执行的写命令;
(4)从数据库收到快照文件后丢弃所有旧数据,载入收到的快照;
(5)主数据库快照发送完毕后开始向从数据库发送缓冲区中的写命令;
(6)从数据库完成对快照的载入,开始接收命令请求,并执行来自主数据库缓冲区的写命令;(从数据库初始化完成)
(7)主数据库每执行一个写命令就会向从数据库发送相同的写命令,从数据库接收并执行收到的写命令(从数据库初始化完成后的操作)
4.2.2 断开重连流程
(1)2.8之后的版本会将断线期间的命令传给从据库,增量复制。
(2)主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。Redis 的策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。
redis的数据量如果过大,在从节点上线节点过多会导致从节点恢复时间过长,同时从节点有大量读请求。
4.2.3 优缺点
优点:
(1) 读写分离:在从节点读;主节点写
(2) Slave 同样可以接受其它 Slaves 的连接和同步请求
(3) Master Server 是以非阻塞的方式为 Slaves 提供服务。所以在 Master-Slave 同步期间,客户端仍然可以提交查询或修改请求;
(4) Slave Server 同样是以非阻塞的方式完成数据同步。在同步期间,如果有客户端提交查询请求,Redis则返回同步之前的数据;
缺点:
(1) Redis不具备自动容错和恢复功能
(2) Slave 断线了,需要重启的时候,尽量不要在同一时间段进行重启。因为只要 Slave 启动,就会发送sync 请求和主机全量同步,当多个 Slave 重启的时候,可能会导致 Master IO 剧增从而宕机
(3) Redis 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂;
sentinel模式是建立在主从模式的基础上的。哨兵模式是一种特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个 Redis 实例(可以理解成挂了一个旁路的监控系统)。
一个哨兵进程对Redis服务器进行监控,也可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。哨兵模式的集群最少需要三个节点,因为存在选主机制
4.3.1 哨兵模式流程
当master节点挂了后,sentinel会在slave中选一个作为master,并修改他们的配置文件,其他slave的配置文件也会被修改,比如slaveof属性会指向新的master。当Master节点重新启动后,它将不再是Master而是作为slave来接收新的master节点的同步数据。
4.3.2 优缺点
优点
(1) 读写分离:在从节点读;主节点写
(2) Slave 同样可以接受其它 Slaves 的连接和同步请求
缺点
(1) Redis 主从模式要复杂一些,原理理解更繁琐
(2) 心化的集群实现方案:始终只有一个Redis主机来接收和处理写请求,写操作受单机瓶颈影响
(3) Sentinel基本已经实现了高可用,但是每台机器都存储相同内容,很浪费内存,所以Redis Cluster实现了分布式存储
(4) Redis主节点宕机后,开启保护机制,禁止写操作,直到选举出了新的Redis主机
redis cluster模式是redis的分布式解决方案,当遇到单机内存、并发、流量等瓶颈时,可以采用cluster模式,达到负载均衡的目的。集群部署至少要 3 台以上的master节点,这是规定,所以最好使用3主3从六个节点的模式。
4.4.1 redis集群分片原理
redis数据分片使用的是hash slot, redis集群有16384个哈希槽,每个Key通过CRC16校验后对16384取模来决定放置哪一个槽。当存取redis key时候,redis会根据CRC16算法得到一个结果,然后把结果和16384求余,通过这个值去对应得节点获取数据。
客户端只需要连接其中任意一个节点即可,然后Redis Cluster 中每个节点都保存了其他节点得槽信息。这样当存取key计算完槽之后,通过保存槽信息从配置中获取节点信息,然后再去对应得节点获取数据。
4.4.1.1 指派槽位
通过命令 CLUSTER ADDSLOTS <slot> [slot...] 命令我们可以将一个或多个槽指派给某个节点。在哪个节点执行就指派给哪个节点,但是槽位信息必须没有被其他节点使用。设置后节点将会将槽指派的信息发送给其他集群,让其他集群更新信息。
计算哈希槽位置其实使用的是CRC16算法对键值进行计算后再对16383取模得到最终所属插槽也可以使用 CLUSTER KEYSLOT <key> 进行查看。
4.4.2 高可用
Redis的每个节点都可以分为主节点与对应从节点。主节点负责处理槽,从节点负责复制某个主节点,并在主节点下线时,代替下线的主。主节点A和它的从节点A1都宕机,那么该集群就无法再提供服务。因为不同的数据存储在不同的槽位中
4.4.3 故障转移
Redis的每个节点都会定期向其他节点发送Ping消息,以此来检测对方是否在线。当一个节点检测到另一个节点下线后,会将其设置为疑似下线。如果一个机器中,有半数以上的节点将某个主节点设为疑似下线,则该节点将会被标记为已下线状态,并开始执行故障转移。
故障转移流程:
(1) 通过raft算法从下线主节点的从节点中选出新的主节点
(2) 被选中的从节点执行 SLAVEOF no one 命令,成为新的主节点
(3) 新的主节点撤销掉已下线主节点的槽指派,并将这些槽指给自己
(4) 新的主节点向集群中广播自己由从节点变为主节点
(5) 新的主节点开始接受和负责自己处理槽的有关命令请求
4.4.4 优缺点
优点:
(1) 实现了分布式存储,节省了内存
(2) 可扩展性
(3) 高可用性
缺点:
原理复杂?
5.1.1 redis下载
下载地址:https://redis.io/download/
5.1.2 解压
tar -zxvf redis-2.4.14.tar.gz
5.1.3 编译及安装
1、执行make 对Redis解压后文件进行编译,编译完成之后,可以看到解压文件redis-3.0.7 中会有对应的src、conf等文件夹。
2、编译成功后,进入src文件夹,执行make install进行Redis安装。
5.1.4 配置
复制redis.conf到/conf/下,修改配置文件,来配置redis服务器。
vi /conf/redis.conf
5.2.1 启动、停止redis
3.2.1 启动redis
进入到bin下面,启动方式有一下几种:
1、直接执行https://blog.csdn.net/liyue/article/details/ redis-server,采用默认配置启动,前台启动。
2、直接执行https://blog.csdn.net/liyue/article/details/ redis-server &,采用默认配置启动,后台启动。
后台启动需要conf文件中daemonize属性改为yes
3、Redis-server https://blog.csdn.net/liyue/article/details/usr..https://blog.csdn.net/liyue/article/redis.conf & 启动redis服务,并指定配置文件
4、测试启动 redis-cli ping 返回PONG,启动成功。(集群模式不适用,可以直接查看进程)
查看端口是否被占用:netstat –ntlp |grep 6379
3.2.2 停止redis
Pkill redis-server 关闭redis服务
redis-cli shutdown 关闭redis客户端
redis-cli -p 6380 shutdown 关闭指定端口的客户端
3.2.3 连接redis
两种连接方式:
1:window DOS方式:tentel主机IP端口号(默认为127.0.0.1:6379)
2:linux客户端方式:redis-cli 连接默认
Redis-cli –p prot –h host 连接制定ip和端口的
要让集群正常工作至少需要3个主节点,在这里我们要创建6个redis节点,其中三个为主节点,三个为从节点,对应的redis节点的ip和端口对应关系如下)
127.0.0.1:7000
127.0.0.1:7001
127.0.0.1:7002
127.0.0.1:7003
127.0.0.1:7004
127.0.0.1:7005
下载地址:http://www.redis.cn/ 注:必须是3.0以上版本
tar -zxvf redis-3.0.0-rc2.tar.gz
mv redis-3.0.0-rc2.tar.gz redis3.0
cd /usr/local/redis3.0
make
make install
mkdir -p /usr.local/cluster(目录可以自定义)
cd /usr.local/cluster
mkdir 7000
mkdir 7001
mkdir 7002
mkdir 7003
mkdir 7004
mkdir 7005
cp /usr/local/redis3.0/redis.conf /usr.local/cluster
vi redis.conf
修改配置文件中的下面选项
port 7000
bind 0.0.0.0 -::
pidfile /var/run/redis-7000.pid
dbfilename dump-7000.rdb
dir /usr/local/redis
maxclients 10000
maxmemory //设备内存64G设置为20G,128G设置为40G
maxmemory-policy volatile-ttl
maxmemory-samples 5
logfile "/var/log/redis/redis-7000.log"
appendfilename "appendonly-7000.aof"
cluster-config-file nodes-7000.conf
cluster-enabled yes
cluster-node-timeout 5000
appendonly yes
修改完redis.conf配置文件中的这些配置项之后把这个配置文件分别拷贝到7000/7001/7002/7003/7004/7005目录下面.然后对应修改
cp /usr/local/cluster/redis.conf /usr/local/cluster/7000
cp /usr/local/cluster/redis.conf /usr/local/cluster/7001
cp /usr/local/cluster/redis.conf /usr/local/cluster/7002
cp /usr/local/cluster/redis.conf /usr/local/cluster/7003
cp /usr/local/cluster/redis.conf /usr/local/cluster/7004
cp /usr/local/cluster/redis.conf /usr/local/cluster/7005
6.5.1 启动redis
进入bin下面,启动命令:/home/redis/redis-3.2.4/src/redis-server /home/redis/redis-3.2.4/redis_cluster/7000/redis.conf &(绝对)
6.5.2 查看启动
使用命令查看redis的启动情况ps -ef|grep redis,如图下标识启动成功:
命令:cd /usr/local/redis3.0/src
https://blog.csdn.net/liyue/article/details/redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 (注:IP地址和端口请根据实际情况填写)
执行创建时可能会报错,是因为因为是执行的ruby的脚本,需要ruby的环境。
Ruby安装见后面
输入yes,然后配置完成
Redis5.0后创建集群不需要使用ruby,可以直接使用redis-cli –cluster create。命令如下:
redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1 
6.8.1 进入集群
进入集群有两种方式:
1、 进入redis的src目录下执行https://blog.csdn.net/liyue/article/details/redis-cli -c -p 7000 -h 172.16.12.3
2、 直接在任意目录下执行redis-cli -c -p 7000 -h 172.16.12.3
注:一定要加上-c
6.8.2 退出redis集群
Redis集群没有没有管理节点,节点都是对等的,杀掉所有节点pkill -9 redis
flushdb 删除当前选择数据库中的所有key
flushall 删除所有数据库中的数据库
新增一个master节点,确保该节点没有存储过数据。增加流程:启动需要增加的redis节点、将节点添加到集群中、分配槽位、给主节点分配从节点
7.1.1 将节点增加到集群中
redis-cli --cluster add-node {新节点IP:PORT} {集群中任一节点IP:PORT}
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
7.1.2 给增加的节点分配槽位
新增加的节点时没有槽位的,可以通过命令查看
需要手动分配操作,执行redis-cli --cluster reshard 127.0.0.1:7000。节点信息可以是集群中任意一个节点。四个节点平分4096个槽位,然后选择7006节点的id。槽位分配可以选择手动从不同节点选取,也可以选择all自动平均从三个主节点分配。
分配槽位的配置信息:
(1) 需要移动的槽位数
(2) 需要移动到哪个节点,填写节点id
(3) 需要从哪几个节点移动到上述节点
(4) 确认移动策略,填写yes/no
分配完成后可以通过命令查看分配后的槽位信息
7.1.3 给新的主节点分配从节点
进入到节点7007后台,执行以下命令,id为给其分配的主节点的id。
cluster replicate b5584bf15f2a852adef8b7720f9ca8a36452b6b1
删除节点的流程为:删除主节点的从节点、移除主节点的槽位、删除主节点
7.2.1 删除从节点
删除节点的ip+port和id必须都带上,并且对应一致。
redis-cli --cluster del-nodes 127.0.0.1:7007 b3275feaca937c14b05af719aaf8ac306
7.2.2 移除主节点槽位
移动的槽位数必须大于此节点的槽位数才可以完全移除完
redis-cli --cluster reshard 127.0.0.1:7006
7.2.3 删除主节点
redis-cli --cluster del-node 127.0.0.1:7006 b5584bf15f2a852adef8b7720f9ca8a36452b6b1
(1) 沟通命令,查看状态
连接到客户端之后,输入ping,redis返回pong。表示redis能够正常运行。

(2) 查看当前数据库中key的数量:dbsize

(3) 切换库命令:select db。集群模式只支持使用database 0

(4) 删除当前数据库的所有数据:flushdb

(5) 删除所有数据库的所有数据:flushall

(6) 查看运行信息命令info [section]

(7) 查看配置信息命令 CONFIG GET [section]

(1) 查看集群配置:info cluster

(2) 查看集群信息:cluster info

(3) 查看集群节点信息:cluster nodes

(4) 查看集群槽位分配:cluster slots

(5) 查看key所分配的槽位:cluster keyslot key_tset

语法
功能
keys pattern
查看数据库所有符合pattern的key
exists key [key…]
判断key是否存在
expire key seconds
设置 key 的生存时间,超过时间,key 自动删除。单位是秒
ttl key
以秒为单位,返回 key 的剩余生存时间(ttl: time to live)
type key
查看 key 所存储值的数据类型
del key [key…]
删除存在的 key,不存在的 key 忽略。
https://blog.csdn.net/Luna_A/article/details/
8.4.1 字符串-string
字符串类型是 Redis 中最基本的数据类型,它能存储任何形式的字符串,包括二进制数据,序列化后的数据,JSON 格式数据
1、 set
语法:set key value
把value的值赋给key
2、 get
语法:get key
获取key的value
3、 incr
语法:incr key
将 key 中储存的数字值加 1,如果 key 不存在,则 key 的值先被初始化为 0 再执行incr 操作(只能对数字类型的数据操作)
4、 decr
语法:decr key
将 key 中储存的数字值减1,如果 key 不存在,则么 key 的值先被初始化为 0 再执行 decr 操作(只能对数字类型的数据操作)
5、 append
语法:append key value
如果 key 存在,则将 value 追加到 key 原来旧值的末尾
如果 key 不存在,则将 key 设置值为 value
返回值:追加字符串之后的总长度
6、 strlen
语法:strlen key
返回key存储的value的总长度,key不存在返回0
7、 getrange
语法:getrange key start end
作用:获取 key 中字符串值从 start 开始到 end 结束的子字符串,包括 start 和 end, 负数表示从字符串的末尾开始,-1 表示最后一个字符
返回值:截取的子字符串。
8、 setrange
语法:setrange key offset value
说明:用 value 覆盖(替换)key 的存储的值从 offset 开始,不存在的 key 做空白字符串。
返回值:修改后的字符串的长度
9、 mset
语法:mset key value [key value…]
说明:同时设置一个或多个 key-value 对
返回值:OK
10、 mget
语法:mget key [key …]
作用:获取所有(一个或多个)给定 key 的值
返回值:包含所有 key 的列表
8.4.2 哈希类型-hash
8.4.3 列表类型-list
8.4.4 集合类型-set
8.4.5 有序集合-zset
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/hd-yjs/17883.html