Redis——从入门到入赘
本redis学习笔记是我学习过程的记录,学习自周阳老师,如有不足之处请多指教
Redis
1. 前言
在学习reids之前,有一些背景和概念需要我们先去认识,这样学期redis起来会更加融会贯通;我们首先认识的便是NoSQL(大家可以结合菜鸟教程来学习)
1.1 什么是NoSQL?
NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL"。泛指非关系型数据库。
在今天爆炸式增长的用户数据中,这类数据存储不需要固定的模式,也无需多余的操作就可以横向扩展了。NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,特别是大数据应用难题。
1.2 为什么使用NoSQL?
随着互联网的发展,互联网用户各种信息和业务资源等数据已成几何倍的增加(海量,多样和实时),如果我们对这些用户数据进行挖掘,那传统的SQL数据库已经不再适合了,而NoSQL数据库的发展能很好的适应这种大数据的操作(高并发,高可扩和高性能)
1.3 NoSQL特点
- 易扩展
nosql数据库种类繁多,但是一个共同的特点就是去掉了关系数据库的关系型特性,数据间无关系,这样就容易扩展了。无形间也在架构层面上带来了可扩展的能力 - 大数据量高性能
由无关系性的特性使得nosql数据库的结构简单,具有非常高的读写性能。相较于mysql的Query Cache(一种大颗粒的Cache),每次表的更新cache就失效;而nosql的cache是记录级的,是一种细粒度的cache,性能更高 - 灵活多样的数据模型
nosql无需事先为要存储的数据建立字段,随时可存储自定义的数据格式。对比关系数据库,大数据量的表增加字段简直就是噩梦!
1.4 传统RDBMS VS NOSQL
RDBMS
- 高度组织化结构化数据
- 结构化查询语言sql
- 数据和关系都存储在单独的表
- 数据操纵语言,数据定义语言
- 严格的一致性
- 基础事务
nosql
- 不仅仅是sql
- 没有声明性查询语言
- 没有预定义的模式
- 键值对存储,列存储,文档存储,图形数据库
- 最终一致性,而非ACID
- 非结构化和不可预知的数据
- CAP定理
- 高性能,高可用性和可扩展性
1.5 nosql数据库分类
类型 | 代表 | 特点 |
---|---|---|
列存储 | Hbase、Cassandra、Hypertable | 顾名思义,是按列存储数据的。最大的特点是方便存储结构化和半结构化数据,方便做数据压缩,对针对某一列或者某几列的查询有非常大的IO优势。 |
文档存储 | MongoDB、CouchDB | 文档存储一般用类似json的格式存储,存储的内容是文档型的。这样也就有机会对某些字段建立索引,实现关系数据库的某些功能。 |
key-value存储 | Tokyo Cabinet / Tyrant、Berkeley DB、MemcacheDB、Redis | 可以通过key快速查询到其value。一般来说,存储不管value的格式,照单全收。(Redis包含了其他功能) |
图存储 | Neo4J、FlockDB | 图形关系的最佳存储。使用传统关系数据库来解决的话性能低下,而且设计使用不方便。 |
对象存储 | db4o、Versant | 通过类似面向对象语言的语法操作数据库,通过对象的方式存取数据。 |
xml数据库 | Berkeley DB XML、BaseX | 高效的存储XML数据,并支持XML的内部查询语法,比如XQuery,Xpath。 |
主要以前四种为常用
1.6 分布式数据库CAP原理
关系型数据库遵循ACID规则:A (Atomicity) 原子性、C (Consistency) 一致性、I (Isolation) 独立性和D (Durability) 持久性
1.6.1 CAP定理(CAP theorem)
- 一致性(Consistency) (所有节点在同一时间具有相同的数据)
- 可用性(Availability) (保证每个请求不管成功或者失败都有响应)
- 分隔容忍(Partition tolerance) (系统中任意信息的丢失或失败不会影响系统的继续运作)
1.6.2 CAP的三选二
CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三大类:
- CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
- CP - 满足一致性,分区容忍性的系统,通常性能不是特别高。
- AP* - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。
分区容忍性是我们必须要实现的;所以我们只能在一致性和可用性间权衡,没有nosql能同时保证这三点
1.6.3 BASE
BASE是未来解决关系数据库强一致性引起的问题而引起的可用性降低而提出的解决方案
- Basically Availble --基本可用
- Soft-state --软状态/柔性事务。 "Soft state" 可以理解为"无连接"的, 而 "Hard state" 是"面向连接"的
- Eventual Consistency -- 最终一致性, 也是 ACID 的最终目的
核心思想:让系统放松对某一时刻数据的一致性来唤起系统整体伸缩性和性能上的改观。
2. 入门
2.1 什么是Redis?
REmote DIctionary Server(Redis) 是一个由 Salvatore Sanfilippo 写的 key-value 存储系统,是跨平台的非关系型数据库。Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储数据库,并提供多种语言的 API。Redis 通常被称为数据结构服务器,因为值(value)可以是字符串(String)、哈希(Hash)、列表(list)、集合(sets)和有序集合(sorted sets)等类型。
redis支持异步将内存中的数据写到硬盘上,同时不影响继续服务;多用于取最新的n个数据的操作,如把最新的10条评论的id放在redis的list集合中;模拟类似于HttpSession这种需要设定过期的功能;发布和订阅消息系统;定时器、计数器等
2.2 特点
- 数据持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
- 多数据类型,同时还提供list,set,zset,hash等数据结构的存储。
- 数据备份,即master-slave模式的数据备份。
2.3 下载与安装
请大家自行去官网或github上下载,可参考菜鸟教程进行安装,这里就不再赘述啦
大家尽量在linux环境下进行操作和学习,阳哥用的是centos,我这边为了方便,就直接用电脑上的Ubuntu~
2.3.1 备份
把redis.config拷贝到自己的文件夹中
2.3.2 配置
redis默认不会以demo进程在后台运行,而我们需要,我们进行以下的操作
vim redis.config
,找到GENERAL,把daemonize no改成daemonize yes
2.3.3 helloworld
下面我们来启动和使用redis吧~
启动时我们也可以验证redis是否在后台运行
2.4 启动后杂项基础知识
- redis是单进程,通过
epoll
函数的包装来对读写事件的处理 - redis内置了16个库(从0开始),通过
select + 角标
来选择对应的库;如select 6
- 查询命令:
-DBSIZE
:查询当前数据库key数量
-keys *
:查询当前数据库所有key
-keys k?
:查询当前数据库以 k 为前缀的key
-FLUNSHDB
: 清空当前库
-FLUNSHALL
:清空全部库 - 16个库的密码都是一致的
2.5 五大常用类型
先讲一下 key关键字 的常用方法
exists key
:判断是否存在key,存在返回1,反之0move key db
:将key的内容移动到目标库,例如move k1 2
expire key second
:设置key过期事件ttl key
:查看还有多少秒过期;-1表永不过期,-2表已过期type key
:查看key类型
2.5.1 String
redis最基本的类型,约等于Memcached,都是一个key对应一个value;string是二进制安全的,即可以包含任何数据,如jpg图片或序列化对象;一个字符串最多可以容纳512m;单key单value
set
:设置get
:获取append key value
:在目标key后追加指定内容strlen key
:返回长度incr key
:递增一,数字才有效,下同decr key
:递减一incrby key num
:递增指定数值decrby key num
:递减指定数值getrange key s l
:获取字符串从第s-1位开始,l个内容,如getrange k1 2 -1
:代表获取k1的第三位开始到最后setrange key s xxx
:设置key第s-1位开始内容位xxx
settx key second
:设置key能存活second秒setnx k1 k3
:设置,会先判断目标是否存在mset/mget/msetnx
:多人运动版的get/set
2.5.2 Hash *
是一个string类型的field和value的映射表,特别适合存储对象;类似java中的Map<String,Object>;KV模式不变,但V是一个键值对
hset/hget/hmset/hmget/hgetall/hdel
:设值/获取/多数设值/多数获取/获取全部/删除
hlen
:返回长度hexists key value
:判断key中的value是否存在hkeys/hvals
:单独遍历key/valuehincrby/hincrbyfloat
:递增指定数值,如hincrby/hincrbyfloat user age 2/2.2
让user的age每次递增2/2.2hsetnx
:类比string,设置前会先判断是否存在
2.5.3 List
最简单的字符串列表,按照插入顺序排序;可以添加一个元素导入列表的头部(左边)或尾部(右边);底层是链表;单key多value
-
lpush/rpush/lrange
:创建列表 -
lpop/rpop
:弹出
-
lindex list01 2
:获取list01索引下标为2的元素,从上至下 -
llen list01
:返回长度 -
lrem list01 2 3
:删除list01中两个3元素 -
ltrim key
:截取指定范围内的值再赋值给key
-
rpoplpush 源列表 目标列表
:右弹出源列表,左加到目标列表
-
lset key index value
:更替指定元素
-
linsert key before/after 值1 值2
:在值1的前/后添加元素
List是一个字符串链表,左右都可以插入;如果键不存在则创建新链表;反之新增内容;如果值全移除,对应键也消失;链表的操作无论是头尾效率都很高,但如果是对中间元素操作,效率就不行了
2.5.4 Set
是string类型的无序,不允许重复的集合,通过HashTable实现;单key多value
sadd/smembers/sismember
:创建/查看/判断;具体见下
scard set01
:获取集合元素个数srem key value
:删除集合某个元素srandmember key
:随机出几个数spop key
:随机出栈smove set01 set02 value01
:将set01的value01赋值给set02sdiff
:差集,在第一个不在第二个中sinter
:交集sunion
:并集
2.5.5 zset(sorted set:有序集合)
和set一样也是string类型的集合且不允许有重复的成员;不同的是每个元素都会关联一个double类型的分数,redus正是通过这个分数来为集合中的成员及逆行从小到大的排序;zse的成员是唯一的,但分数(score)可以重复哦
在set基础上加一个score值,之前set 是k1 v1 v2 v3,现在zset是k1 score1 v1 score2 v2
zadd
:添加zrange(withscore)
:查看加上 withscore ,则带上score一起显示
zrangebuscore key 60 90
:范围查找60~90的内容;加上( 表示不包括;limit表示限制
zrem key 某score下对应的value值
:删除元素zcard/zcount key score区间/zrank key values值
:获取下标/zscore key 对应值,获得分数zrevrank key values值
:逆序获取下标值zrevrange
:逆序获取zrevrangebyscore key 结束socre 开始score
:根据socore逆序获取
常用命令大家可以到这里查看~
3. Redis进阶
我们前面安装redis的过程中,发现了有个redis.comf配置文件,我们也改了其中的一小部分,在实际开发工作中,很大部分的时间都会用于对redis配置的设置;在linux下开发,配置大于编码,所以本节就来讲讲redis中的配置要点
3.1 配置文件详解
我们打开redis.conf配置文件,开头定义了度量单位,要注意不同的写法代表的具体大小不同
当需要配置的点比较多,如果都写在一个配置文件中就会显得很臃肿而且不方便维护,这样我们可以把配置内容分成几个模块,通过 includes
对其进行包含,redis.conf作为总闸来包含其他配置文件
3.1.1 配置汇总(常用)
- Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程daemonize no
- 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定pidfile/var/run/redis.pid
- 指定Redis监听端口,默认端口为6379,作者在自己的一篇博文中解释了为什么选用6379作为默认端口,因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字
port 6379 - 绑定的主机地址
bind 127.0.0.1 - 当客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
timeout 300 - 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose loglevel verbose
- 日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null logfile stdout
- 没置数据库的数量,默认数据库为0,可以使用SELECT
命令在连接上指定数据库id databases 16 - 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合save
Redis默认配置文件中提供了三个条件:
save 9001
save 30010
save 6010000I分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。 - 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大rdbcompression yes
- 指定本地数据库文件名,默认值为dump.rdb dbfilename dump.rdb
- 指定本地数据库存放目录
dir./ - 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步slaveof
- 当master服务设置了密码保护时,slav服务连接master的密码
masterauth - 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH
命令提供密码,默认关闭requirepass foobared; config get requirepass
:获取当前的用户密码;config set requirepass "123456"
:设置当前用户密码 - 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置maxclients0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息maxclients 128
- 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理后,仍然到达最大
内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区maxmemory - 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no
- 指定更新日志文件名,默认为appendonly.aof appendfilename appendonly.aof
- 指定更新日志条件,共有3个可选值:
no:表示等操作系统进行数据缓存同步到磁盘(快)always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)evervsec:表示每秒同步一次(折衷,默认值)appenafsync everysed - 指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制)vm-enabled no
- 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享vm-swap-file/tmp/redis.swap
- 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0
vm-max-memory 0 - Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;如果存储很大大对象,则可以使用更大的page,如果不确定,就使用默认值vm-page-size32
- 设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。
vm-pages 134217728 - 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4
vm-max-threads 4 - 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启
glueoutputbuf yes - 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法
hash-max-zipmap-entries 64
hash-max-zipmap-value 51229.指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍) - 指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍)activerehashing yes
- 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件include/path/to/local.conf
查看后台运行情况命令:ps -ef|grep redis
,lsof -i :6379
3.2 持久化
内存中的数据是易丢失的,暂时的,我们要将这些数据写入到非易失介质中(如硬盘)的操作,就叫持久化;redis的持久化分为RDB和AOF
3.2.1 RDB
在指定时间内将内从数据快照写入磁盘;redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入一个临时文件,等持久化过程结束,再把这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能,如果需要进行大规模的数据恢复,且对数据恢复的完整性不是很敏感,那RDB比AOF更高效,RDB的缺点是最后一次持久化后的数据可能会丢失;RDB保存的是dump.rdb
fork:复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都与原进程一致,但这是一个全新的进程,是原进程的子进程
在redis.config配置文件中的SNAPSHOTTING部分就是持久化的配置,redis默认已经设置了三种备份的情况了;当然,我们如果要马上就备份,可以直接执行 save
,就会立即执行备份啦
其他命令:
stop-writes-on-bgsave-error
:设置成no,表示不在乎数据一致性或有其他的手段发现和控制rdbcompression
:压缩rdbchecksum
:校验,但会消耗10%的性能dbfilename
:设置所要读取的备份文件名dir
:获取目录
如何触发快照
- 配置文件中默认的快照配置-冷拷贝后重新使用-可以
cp dump.rdb dump_new.rdb
- 使用
save
或bgsave
:save只管保存,其他不管,全部阻塞;bgsave会在后台异步快照,同时可以响应客户端请求,可以通过lastsave
获取最后一次成功执行快照的时间 flushall
:无意义,内容是空的
如何恢复
- 将备份文件dump.rdb移动到redis安装目录并启动服务
CONFIG GET dir
:获取目录
优劣势
优势:适合大规模数据恢复;对数据完整性和一致性要求不高
劣势:在一定是个做一次备份,如果redis意外down掉,就会丢失最后一次快照的所有修改;fork时,内存的数据被克隆一份,大致2倍的膨胀性需要考虑
如何停止
动态所有停止RDB保存规则的方法:redis-cli config set save ""
总结
rdb是一个非常紧凑的文件,在需要保存rdb文件时父进程唯一要做的工作全由子进程完成,父进程不需要再做其他IO操作,所以rdb持久化方法可以最大化redis性能;与AOF相比,在恢复大数据集时会更快
但是数据丢失风险大;rdb需要常fork子进程保存数据集到硬盘,当数据集比较大时,fork过程很耗时,可能会导致redis在毫秒级不能响应客户端请求
3.2.2 AOF
我们知道RDB会丢失最后一次快照的所有修改,AOF是新生事物,自然要来解决RDB老前辈的缺点~
AOF以日志形式记录每个写操作,将redis执行过的所有写指令记录(无视读操作),只许追加文件但不可改写文件,redis启动之处会读取该文件重构建数据,即redis重启会根据日志文件将写指令从前往后执行一遍以达到恢复工作;如果redis存在两种备份策略,优先调用aof,但是rdb还存在;如果aof文件出错,我们可以执行redis-check-aof --fix appendonly.aof
来对aof文件中不符合语法规范或错误的地方进行休整
我们可以在配置文件中找到 APPEND ONLY MODE 部分,就是关于aof的配置内容
appendonly yes
:开启aof
appendfilename "appendonly.aof"
:备份文件名
appendfsync everysec
:always表同步持久化,每次发生数据变更都会被立即记录到磁盘,性能较差但数据完整性好;everysec是默认推荐的,异步操作,每秒记录,如果一秒内宕机,有数据丢失;no
AOF启动/修复/恢复
正常恢复:
- 启动:修改默认的appendonly no为yes
- 将有数据的aof文件复制一份保存到对应目录(config 个dir)
- 恢复:重启redis然后重新加载
异常恢复: - 启动:设置yes
- 备份被写坏的aof文件
- 修复:redis-check-aof -- fix进行修复
- 恢复:重启redis然后重新加载
Rewirte重写
aof采用文件追加方式,文件会越来越大,为避免这种情况,新增了重写机制,当aof文件的大小超过了所设定的阈值时,redis就会启动aof文件的内容压缩,只保留可以恢复数据的最小指令集,可以使用命令
bgrewriteaof
重写原理
aof文件持续增长而过大时,会fork一条新进程来将文件重写(也是险些临时文件最后再rename),遍历新进程的内存中数据,每条记录有一条的set语句,重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件
触发机制
reids会记录上次重写时的aof大小,默认配置是当aof文件大小是上次rewrite后大小的已被且文件大于64m时触发
No-appendfsync-on-rewrite
:重写时是否可以运用Appendfsync,用默认的no即可,保证数据安全性auto-aof-rewrite-min-size
:设置重写的基准值auto-aof-rewrite-percentage
:设置重写的基准值
优劣势
优势:完整性高
劣势:备份文件远大于rab,恢复速度和运行效率慢于rdb,每秒同步策略效率较好,不同步效率和rdb相同
总结
aof文件是一个只进行追加的日志文件,redis可以在aof文件变得过大时自动在后台进行重写;对于相同的数据集,aof文件的体积通常要大于rdb文件;根据所使用的fsync策略,aof的速度可能会慢于rdb
只做缓存:如果只希望我们的数据在服务器运行时存在,我们可以不使用任何持久化方式,但是建议同时开启两种持久化方式
3.3 事务
可以自此执行多个命令,本质是一组命令的集合,一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其他命令插入,不许阻塞
3.3.1事务命令
3.3.2演示
3.3.3 watch监控
悲观锁:总是假设最坏的情况,每次取数据都认为别人也会修改,所以每次取的时候就上锁,这样别人要修改数据就会阻塞直到他拿到锁。传统关系型数据库就用到很多锁的机制,如行锁,表锁,读锁和写锁等,都是在操作前上锁。java的synchronized和ReentrantLock等独占锁就是悲观锁的思想体现
乐观锁:总是假设最好的情况,每次取数据都不认为有人会修改,就不上锁了,但是在更新提交时会判断这期间是否有人更新数据,一般是通过版本号机制和CAS算法实现的(即提交版本必须大于记录当前版本才能执行更新)。乐观锁多用于读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制。在java中 java.util.concurrent.atomic包下的原子变量类就是使用了乐观锁CAS方式实现的
watch类似乐观锁,事务提交时,如果key的值已被其他客户端改变了,如某个list已被其他客户端push/pop过了,整个事务队列都不会被执行;通过watch命令的事务执行前监控了多个keys,如果在watch之后又任何key的值发生变化,exec命令执行的事务都将被放弃,同时返回Nullmulti-bulk应答以通知调用者事务执行失败
一旦执行了exec,之前加的监控所都会被取消掉
3.4 消息订阅发布
消息订阅是进程间的一种消息通信模式:发送者(pub)发送信息,订阅者(sub)接收消息;redis的消息订阅很少用,一般使用其他中间件
下图展示了频道channel1,以及订阅这个频道的三个客户端间的关系
当有新消息通过PUBLISH命令发送给频道channel1时,这个消息就会被发送给订阅他的三个客户端
3.4.1 常用命令
3.4.2 案例
3.5 redis的复制
也就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,master以写为主,slave以读为主;主要包括读写分离和容灾恢复
3.5.1 怎么玩?
- 配从不配主
- 从库配置:
slaveof 主库IP 主库端口 每次与master断开后都需要重连,除非我们配置进redis.conf文件;
info replication`可以读取当前数据库的属性情况 - 修改配置文件细节操作
- 拷贝多个redis.conf文件
- 开启daemonize yes
- Pid文件名字
- 指定端口
- Log文件名称
- Dump.rdb名字
- 常用三招
- 一主二仆:从机不能进行写操作,只有主机才可以写,从机只能进行读操作;如果主机死了,从机身份依旧是从机
- 薪火相传:例如A是master,B是跟随A的slave,C是跟随B的slave,则B和C都可以获取A的数据库信息
- 反客为主:在一主二仆中,如果master挂了,不做任何操作,则两个slave按兵不动,依旧是master的slave;如果master挂了,其中一个slave可以执行
SLAVEOF no one
来夺取master的身份,而另一个slave需要重新指定master才行,否则依旧是原地待命;如果旧master恢复了,则自己是一套体系,和新体系无关联
3.5.2 复制原理
slave启动成功连接到master后会发出一个sync命令;master街道命令启动后台的存盘进程,同时手机所有用于修改数据集命令,在后台进程执行完毕后,master将床送整个数据文件到slave,完成一次完全同步;全量复制指slave服务在接收到数据库文件数据后,将其存盘并加载到内存;增量复制指master继续将新的所有收集到的修改命令依次传给slave完成同步;但是只要是重新连接master,一次完全同步(全量复制)将被自动执行
3.5.3 哨兵模式
前面的反客为主需要人工的去切换master,这样很不适合实际要求,毕竟人的反应还有操作都需要时间,这时候就有了哨兵模式啦,既自动波的反客为主;能后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库
- 自定义的/myredis目录下新建sentinel.conf文件(只能叫这个!!)
- 设置哨兵,填写内容:sentinel monitor 被监控数据库名称(自己起) 127.0.0.1 6379 1;最后的 1 表示主机挂掉后slave投票看让谁接替成为主机,得票数多为主机;设置完后在启动目录会出现一个 redis-sentinel 文件
- 启动哨兵
redis-sentinel /myredis/sentinel.conf
如果旧master回来了,就会变成slave;需要注意的是,哨兵模式的复制有延时,由于所有的写操作都是现在master上操作的,然后同步更新到slave上,所以从master同步到slave上有一定的延迟,当系统很繁忙时,延迟问题会更验证,slave机数量的增加也会使延时问题更严重