Redis 学习笔记
Redis
直接进入主题吧
配置 redis 运行环境
Linux - CentOS 7 64 位,安装 Redis
- 将下载后的压缩包上传至 Linux 系统中。
- 解压安装包到
usr/local
目录:tar -zxvf filename.tar.gz -C /usr/local
- 进入到解压后的
redis
目录:cd /usr/local/redis-xxx
- 编译
Redis
文件,Redis
是 c 语言写的,会用到 gcc 编译器,执行make
- 会出现两个错误
- 错误一:gcc 命令找不到,
gcc: Command not found
- 解决错误一:
yum -y install gcc
- 错误二:error: jemalloc/jemalloc.h: No such file or directory
- 解决错误二:
make MALLOC=libc
- 错误一:gcc 命令找不到,
- 会出现两个错误
- 执行
make distclean
清理上次make
后产生的文件 - 执行
make
命令进行编译,成功的标志:make[1]:Leaving directory '/usr/local/redis-3.2.9/src'
- 注意:在
make
执行之后再执行make install
,该操作则将src
下的许多可执行文件复制到/usr/local/bin
目录下,这样做可以在任意目录执行redis
的软件的命令(例如启动,停止,客户端连接服务器等)
Linux - CentOS 7 64 位,启动 Redis
- 进入
redis
的src
目录。 - 启动
redis
,查看是否启动成功ps -ef | grep redis
- 前台启动:
./redis-server
src
目录下执行redis-server
- 以前台的方式启动,不能退出当前窗口,退出窗口,应用终止。
- 后台启动:
./redis-server &
- 前台启动:
Linux - CentOS 7 64 位,关闭 Redis
- 方式一:使用 redis 客户端关闭, 向服务器发出关闭命令
src
目录下,执行./redis-cli shutdown
- 推荐使用这种方式,redis 先完成数据操作,然后再关闭。
- 方式二:kill pid 或者 kill -9 pid
- 这种不会考虑当前应用是否有数据正在执行操作,直接就关闭应用。
- 先使用
ps -ef | grep redis
查出进程号, 在使用kill pid
Linux - CentOS 7 64 位,连接 Redis
redis 命令行客户端
- 方式一:直接连接 redis (默认ip127.0.0.1,端口6379):
./redis-cli
src
目录, 执行./redis-cli
- 方式二:指定 IP 和端口连接 redis:
./redis-cli -h 127.0.0.1 -p 6379
- -h redis 主机 IP(可以指定任意的 redis 服务器)
- -p 端口号(不同的端口表示不同的 redis 应用���
src
目录执行
redis 远程客户端
- Redis Desktop Manager:C++ 编写,响应迅速,性能好。
- Another Redis Desktop Manager
注意事项 :使用远程连接 redis 时,需要修改 redis.conf 配置文件:
- 备份一份配置文件:
cp redis.conf bak_redis.conf
- bind ip 这一行注释掉
- protected-mode yes 保护模式改为 no
- 使用修改后的配置文件后台启动 redis(src 目录下):
./redis-server ../redis.conf &
Redis 基本操作命令
沟通命令,查看状态
redis> ping [message]
作用:输入 ping,redis 返回 pong,表示 redis 服务运行正常。
返回:不加 message 为 PONG
,加 message 为 message。
查看当前数据库中 key 的数量
redis> dbsize
作用:返回当前书库中的 key 的数量。
返回:数字,key 的数量。
redis 默认使用 16 个库
在 redis 配置文件中可以进行修改。
切换数据库命令
redis> select index
作用:切换到指定的数据库。
返回:OK
删除当前数据库中的所有数据
redis> flushdb
作用:清空当前数据库中的所有数据
返回:OK
redis 自带的客户端退出当前 redis 连接
redis> exit
redis> quit
作用:退出当前 redis 连接
Redis 的 Key 的操作命令
查找符合条件的 key
keys pattern
作用:查找所有符合模式 pattern 的 key,pattern 可以使用通配符。
返回:符合条件的 key。
判断一个或多个 key 是否存在
exists key [key...]
作用:判断 key 是否存在
返回:整数,返回存在的 key 的数量。
设置 key 的生存时间
expire key seconds
作用:设置 key 的生存时间,超过时间的 key 自动删除,单位是秒。
返回:设置成功返回 1,其他情况是 0。
查询 key 的剩余生存时间
ttl key
作用:time to live,返回 key 的剩余生存时间
返回:
- -1 表示没有设置 key 的生存时间,key 永不过期;
- -2 表示 key 不存在;
- 数字 表示 key 的剩余时间,单位是秒。
查看 key 所存储值的数据类型
type key
作用:查看 key 对应值的数据类型
返回:
- none 表示 key 不存在
- string 表示 字符串
- list 表示列表
- set 表示集合
- zset 表示有序集
- hash 表示哈希表
删除存在的 key
del key [key...]
作用:删除存在的 key,不存在的 key 忽略。
返回:数字,删除的 key 的数量;不存在的 key 删除时返回 0。
Redis 的 5 种数据类型与操作命令
字符串类型 string
类型介绍
字符串类型是 Redis 中最基本的数据类型,它能存储任何形式的字符串,包括二进制数据,序列化后的数据,JSON 化的对象甚至是一张图片。最大 512 M。
基本命令
- set
redis> set key value
作用:将字符串的值 value 设置到 key 中。
- get
redis> get key
作用:获取 key 中设置的字符串。
返回:不存在的 key 返回 (nil)
- incr
redis> incr key
作用:将 key 中储存的数字值加 1,如果 key 不存在,则 key 的值先被初始化为 0 再执行 incr 操作。
返回:增加后的最终值。
注意:只能对数字类型的数据操作
- incrby
redis> incrby key increment
作用:将 key 中存储的数字值加 increment,如果 key 不存在,则 key 的值先被初始化为 0 再执行 incrby 操作。
返回:增加后的最终值。
- decr
redis> decr key
作用:将 key 中储存的数字值减1,如果 key 不存在,则么 key 的值先被初始化为 0 再执行 decr 操作。
返回:减少后的最终值。
注意:只能对数字类型的数据操作
- append
redis> append key value
作用:如果 key 存在,则将 value 追加到 key 原来旧值的末尾;如果 key 不存在,则将 key 设置值为 value。
返回:追加字符串之后的总长度。
常用命令
- strlen
redis> strlen key
作用:返回 key 所存储的字符串值的长度。
返回:如果 key 存在,返回字符串值的长度;如果 key 不存在,返回 0。
- getrange
redis> getrange key start end
作用:获取 key 中字符串值从 start 开始到 end 结束的子字符串,包括 start 和 end;负数表示从字符串的末尾开始,-1 表示最后一个字符。
返回:截取的子字符串。
例子:
redis> set username zhangsan
OK
redis> getrange username 0 -2
"zhangsa"
redis> getrange username 2 100
"angsan"
- setrange
redis> setrange key offset value
作用:用 value 覆盖(替换)key 对应存储的值,起始位置从 offset 开始,不存在的 key 如果 offset > 0,则起始位置前的内容用空字符串填补。
返回:修改后的字符串的长度。
例子:不存在的 key
redis> setrange password 2 shenjingbing
(integer) 14
redis> get password
"\x00\x00shenjingbing"
- mset
redis> mset key value [key value...]
作用:同时设置一个或多个 kay-value 键值对。
返回:OK
- mget
redis>mget key [key...]
作用:获取所有给定 key 的值。
返回:包含所有 key 的列表。
哈希类型 hash
类型介绍
Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。
基本命令
- hset
redis> hset key field value
作用:将 key 对应的 hash 表中的 field 设置为 value,如果 key 不存在,则新建 hash 表,执行 field、value 的赋值,如果有 field,则覆盖 value。
返回:
- 如果 field 是 hash 表中的新 field,且设置值成功,返回 1。
- 如果 field 已经存在,旧值覆盖新值,返回 0。
- hget
redis> hget key field
作用:获取 hash 表 key 中给定 field 的值。
返回:field 对应的 value 值,如果 key 不存在或者 field 不存在返回 nil。
- hmset
redis> hmset key field [field...]
作用:将 key 对应的 hash 表中的一个或多个 field 设置为 value,如果 key 不存在,则新建 hash 表,执行 field、value 的赋值,如果有 field,则覆盖 value。
返回:设置成功返回 ok , 如果失败返回一个错误
- hmget
redis> hmget key field [field...]
作用:获取 hash 表 key 中一个或多个 field 的值。
返回:返回和 field 顺序对应的值,如果 field 不存在,返回 nil。
- hgetall
redis> hgetall key
作用:获取 hash 表 key 中所有的 field 和 value。
返回:以列表形式返回 hash 中 field 和 value,key 不存在,返回空 hash(empty list or set)。
- hdel
redis> hdel key field [field...]
作用:删除哈希表 key 中的一个或多个指定域 field,不存在 field 直接忽略。
返回:成功删除的 field 的数量。
常用命令
- hkeys
redis> hkeys key
作用:获取指定 key 中的所有 field。
返回:如果 key 存在则返回对应的所有 field,如果 key 不存在则返回(empty list or set)。
- hvals
redis> hvals key
作用:返回 hash 表中所有 field 的值。
返回:包含 hash 表所有 field 的 value 的列表,key 不存在返回空列表(empty list or set)。
- hexists
redis> hexists key field
作用:查看 hash 表 key 中,给定域 field 是否存在。
返回:如果 field 存在,返回 1, 其他(key 或者 field 不存在)返回 0。
列表类型 list
类型介绍
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
基本命令
- lpush
redis> lpush key value [value...]
作用:将一个或多个值 value 插入到列表 key 的表头(最左边),从左边开始加入值,从左到右的顺序依次插入到表头,可以添加重复值。
返回:数字,新列表的长度
- rpush
redis> rpush key value [value...]
作用:将一个或多个值 value 插入到列表 key 的表尾(最右边),各个 value 值按从左到右的顺序依次插入到表尾,可以添加重复值。
返回:数字,新列表的长度
- lrange
redis> lrange key start stop
作用:获取列表 key 中指定区间内的元素,0 表示列表的第一个元素,以 1 表示列表的第二个元素;start , stop 是列表的下标值,也可以负数的下标, -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。 start,stop 超出列表的范围不会出现错误。
返回:指定区间的列表。
- lindex
redis> lindex key index
作用:获取列表 key 中下标为指定 index 的元素,列表元素不删除,只是查询。
返回:指定下标的元素;index 不在列表范围,返回 nil。
- llen
redis> llen key
作用:获取列表 key 的长度。
返回:数值,列表的长度;key 不存在返回 0。
常用命令
- lrem
redis> lrem key count value
作用:count 表示移除元素 value 的个数,count > 0 表示从列表的 左侧 向右开始移除;count < 0 表示从列表的尾部开始移除;count = 0 表示移除表中所有与 value 相等的值。
返回:数值,移除的元素个数。
- lset
redis> lset key index value
作用:将 key 对应的 list 中的 index 处的元素替换为 value。
返回:成功返回 OK,key 不存在返回(error ERR no such key),index 越界返回(error ERR index out of range)
- linsert
redis> linsert key before|after pivot value
作用:将 value 插入列表 key 当中值 pivot 之前还是之后,key 不存在或者 pivot 不存在,不执行任何操作。
返回:成功返回新列表的总长度,pivot 不存在返回 -1,key 不存在返回 0。
- lpop
redis> lpop key
作用:从最左侧删除一个 value。
返回:被删除的 value 值,没有值了返回 nil。
- rpop
redis> rpop key
作用:从最右侧删除一个 value。
返回:被删除的 value 值,没有值了返回 nil。
集合类型 set
类型介绍
Redis 的 Set 是 string 类型的 无序 集合,集合成员是唯一的,即集合中不能出现重复的数据。
基本命令
- sadd
redis> sadd key member [member...]
作用:将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略,不会再加入。
返回:加入到集合的新元素的个数,不包括被忽略的元素。
- smembers
redis> smembers key
作用:获取集合 key 中的所有成员元素,不存在的 key 视为空集合。
返回:所有成员元素。
- sismember
redis> sismember key member
作用:判断 member 元素是否是集合 key 的成员。
返回:member 是集合成员返回 1,其他返回 0。
- scard
redis> scard key
作用:获取集合里面的元素个数。
返回:数字,key的元素个数。 其他情况返回 0。
- srem
redis> srem key member [member...]
作用:删除集合 key 中的一个或多个 member 元素,不存在的元素被忽略。
返回:数字,成功删除的元素个数,不包括被忽略的元素。
常用命令
- srandmember
redis> srandmember key [count]
作用:只提供 key,随机返回集合中一个元素,元素不删除,依然在集合中;提供了 count 时,count 正数, 返回包含 count 个数元素的集合, 集合元素各不相同。count 是负数��返回一个 count 绝对值的长度的集合, 集合中元素可能会重复多次。
返回:一个元素;多个元素的集合。
- spop
redis> spop key [count]
作用:随机从集合中删除一个元素, count 是删除的元素个数。
返回:被删除的元素,key 不存在或空集合返回(empty list or set)。
有序集合类型 zset sorted set
类型介绍
Redis 有序集合 zset 和集合 set 一样也是 string 类型元素的集合,且不允许重复的成员。
不同的是 zset 的每个元素都会关联一个分数(分数可以重复),redis 通过分数来为集合中的成员进行从小到大的排序。
基本命令
- zadd
redis> zadd key score member [score member...]
作用:将一个或多个 member 元素及其 score 值加入到有序集合 key 中,如果 member 存在集���中,则更新值;score 可以是整数或浮点数。
返回:数字,新添加的元素个数。
- zrange
redis> zrange key start stop [withscores]
作用:查询有序集合,指定区间的内的元素。集合成员按 score 值从小到大来排序。start, stop 都是从 0 开始。0 是第一个元素,1 是第二个元素,依次类推。以 -1 表示最��一��成员,-2 表示倒数第二个成员。WITHSCORES 选项让 score 和 value 一同返回。
返回:自定区间的成员集合。
- zrevrange
redis> zrevrange key start stop [withscores]
作用:返回有序集 key 中,指定区间内的成员。其中成员的位置按 score 值递减(从大到小)来排列。其它同zrange 命令。
返回:自定区间的成员集合。
- zrem
redis> zrem key member [member...]
作用:删除有序集合 key 中的一个或多个成员,不存在的成员被忽略。
返回:被成功删除的成员数量,不包括被忽略的成员。
- zcard
redis> zcard key
作用:获取有序集 key 的元素成员的个数。
返回:key 存在返回集合元素的个数,key 不存在,返回 0。
常用命令
- zrangebyscore
redis> zrangebyscore key min max [withscores] [limit offset count]
作用:获取有序集 key 中,所有 score 值介于 min 和 max 之间(包括 min 和 max)的成员,有序成员是按递增(从小到大)排序。min,max是包括在内,使用符号 (
表示不包括。min,max 可以使用 -inf,+inf 表示最小和最大 limit 用来限制返回结果的数量和区间。withscores 显示 score 和 value。
返回:指定区间的集合数据。
- zrevrangebyscore
redis> zrevrangescore key min max [withscores] [limit offset count]
作用:返回有序集 key 中, score 值介于 max 和 min 之间(默认包括等于 max 或 min)的所有的成员。有序集成员按 score 值递减(从大到小)的次序排列。其他同 zrangebyscore。
返回:指定区间的集合数据。
- zcount
redis> zcount key min max
作用:返回有序集 key 中,score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max)的成员的数量。使用 (
可以不包含 min 或 max,也可以使用 -inf,+inf 表示最小值和最大值。
返回:元素的个数。
Redis 事务
事务是指一系列操作步骤,这一系列的操作步骤,要么完全地执行,要么完全地不执行。
Redis 中的事务(transaction)是一组命令的集合,至少是 两个或两个以上 的命令,redis 事务保证这些命令被执行时中间不会被任何其他操作打断。
事务操作的命令
- multi
redis> multi
作用:标记一个事务的开始,事务内的多条命令会按照先后顺序被放进一个队列当中。
返回:总是返回 OK
- exec
redis> exec
作用:执行所有事务块内的命令。
返回:事务内的所有执行语句内容,事务被打断(影响)返回 nil。
- discard
redis> discard
作用:取消事务,放弃执行事务块内的所有命令。
返回:总是返回 OK
- watch
redis> watch key [key...]
作用:监视一个或多个 key,如果在事务执行之前这个或这些 key 被其他命令所改动,那么事务将被打断。
返回:总是返回 OK
- unwatch
redis> unwatch
作用:取消 watch 命令对所有 key 的监视,如果在执行 watch 命令之后,exec 命令或 discard 命令先被执行,那么就不需要再执行 unwatch 了。
返回:总是返回 OK
实现事务
事务正常执行
执行步骤:
- 开启事务
- 向事务队列中加入命令
- 执行事务提交
事务执行exec之前,入队命令错误(语法错误;严重错误导致服务器不能正常工作(例如内存不足)),放弃事务。
结论:事务执行exec之前,入队命令错误,事务终止,取消,不执行。
事务执行exec命令后,执行队列命令,命令执行错误,事务提交
结论:在 exec 执行后的所产生的错误,即使事务中有某个/某些命令在执行时产生了错误,事务中的其他命令仍然会继续执行。Redis 在事务失败时不进行回滚,而是继续执行余下的命令。
Redis这种设计原则是:Redis 命令只会因为错误的语法而失败(这些问题不能在入队时发现),或是命令用在了错误类型的键上面,失败的命令并不是 Redis 导致,而是由编程错误造成的,这样错误应该在开发的过程中被发现,生产环境中不应出现语法的错误。就是在程序的运行环境中不应该出现语法的错误。而 Redis 能够保证正确的命令一定会被执行。再者不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。
Redis 的事务对除语法错误之外的错误概不负责!!!
放弃事务
Redis 的 watch 机制
watch 机制原理:
- 使用 watch 监视一个或多个 key,跟踪 key 的 value 修改情况,如果有 key 的 value 值在事务 exec 执行之前被修改了,整个事务被取消。exec 返回提示信息,表示事务已经失败。
- watch 机制使得事务 exec 变得有条件,事务只有在被 watch 的 key 没有修改的前提下才能执行。不满足条件,事务被取消。
- 使用 watch 监视了一个带 过期时间 的键, 那么即使这个键过期了,事务仍然可以正常执行。
- 大多数情况下,不同的客户端会访问不同的键, 相互同时竞争同一 key 的情况一般都很少,乐观锁能够以很好的性能解决数据冲突的问题。
何时取消 key 的监视:
- watch 命令可以被调用多次。对键的监视从 watch 执行之后开始生效,直到调用 exec 为止。不管事务是否成功执行,对所有键的监视都会被取消。
- 当客户端断开连接时,该客户端对键的监视也会被取消。
- unwatch 命令可以手动取消对所有键的监视。
watch 实例(乐观锁):
模拟两个客户端:A 和 B
A 负责监控 key 并执行事务。
B 负责修改 key 对应的数据。
- 在 A 客户端设置 key:num,value:10
- 在 A 客户端监视 key:num
- 在 A 客户端开启事务 multi
- 在 A 客户端修改 key:num,value:20
- 在 B 客户端修改 key:num,value:30
- 在 A 客户端执行事务 exec
- 在 A 客户端查看 num 的值,A 客户端执行的事务没有提交,因为 watch 的 num 值在 exec 前被修改了,所以放弃事务。
A 客户端:
B 客户端:
持久化
持久化概述
持久化可以理解为存储,就是将数据存储到一个不会丢失的地方,如果把数据放在内存中,电脑关闭或重启数据就会丢失,所以放在内存中的数据不是持久化的,而放在磁盘就算是一种持久化。
Redis 的数据存储在内存中,内存是瞬时的,如果 linux 宕机或重启,又或者 Redis 崩溃或重启,所有的内存数据都会丢失,为解决这个问题,Redis 提供两种机制对数据进行持久化存储,便于发生故障后能迅速恢复数据。
持久化方式
RDB (Redis DataBase)
Redis Database(RDB),就是在指定的时间间隔内将内存中的数据集快照写入磁盘,数据恢复时将快照文件直接再读到内存。
RDB 保存了在某个时间点的数据集(全部数据)。存储在一个二进制文件中,只有一个文件。 默认是 dump.rdb。
RDB 技术非常适合做备份,可以保存最近一个小时,一天,一个月的全部数据。
保存数据是在单独的进程中写文件,不影响Redis的正常使用。
RDB 恢复数据时比其他 AOF 速度快。
实现:
RDB 方式的数据持久化,在 redis.conf 文件中配置即可,默认配置是启用的。
在配置文件 redis.conf 中搜索 SNAPSHOTTING, 查找在注释开始和结束之间的关于 RDB 的配置说明。配置 SNAPSHOTTING 的地方有三处。
- 配置执行 RDB 生成快照文件的时间策略:对 Redis 进行设置, 让它在 N 秒内数据集至少有 M 个 key 改动这一条件被满足时,自动保存一次数据集。
配置格式:save
900 秒内数据集至少 1 个改动:save 900 1
300 秒内数据集至少 10 个改动:save 300 10
60 秒内数据集至少 10000 个改动:save 60 10000
dbfilename:设置 RDB 的文件名,默认文件名为 dump.rdb
dir:指定 RDB 文件的存储位置,默认是
./
当前目录
注意:修改配置前一定要关闭掉 redis 进程哟
总结:
优点:由于存储的是数据快照文件,恢复数据很方便,也比较快。
缺点:
会丢失最后一次快照以后更改的数据。如果你的应用能容忍一定数据的丢失,那么使用 rdb 是不错的选择;如果你不能容忍一定数据的丢失,使用 rdb 就不是一个很好的选择。
由于需要经常操作磁盘,RDB 会分出一个子进程。如果 Redis 数据库很大的话,子进程占用比较多的时间,并且可能会影响 Redis 暂停服务一段时间(millisecond 级别),如果数据库超级大并且服务器 CPU 比较弱,有可能是会达到一秒。
AOF (Append Only File)
Append Only Filed(AOF),Redis 每次接收到一条改变数据的命令时,它将把该命令写到一个 AOF 文件中(只记录写操作,读操作不记录),当 Redis 重启时,它通过执行 AOF 文件中所有的命令来恢复数据。
实现:
AOF 方式的数据持久化,仅需在 redis.conf 文件中配置即可,配置项:
appendonly:默认是 no,改成 yes 就是开启了 AOF 持久化。
appendfilename:指定 AOF 文件名,默认文件名为 appendonly.aof。
dir:指定 RDB 和 AOF 文件存放的目录,默认是
./
appendfsync:配置向 AOF 文件写命令数据的策略:
no
:不主动进行同步操作,而是完全交由操作系统来做,也就是每 30 秒一次,比较快但不是很安全。
always
:每次执行写入都会执行同步,慢一些但是比较安全。
everysec
:每秒执行一次同步操作,比较平衡,介于速度和安全之间,这是默认项。
auto-aof-rewrite-min-size
:允许重写的最小 AOF 文件大小,默认是 64M。当 AOF 文件大于 64M 时,开始整理 AOF 文件,去掉无用的操作命令,缩小 AOF 文件。
注意:修改配置前一定要关闭掉 redis 进程哟
总结:
- append-only 文件是另一个可以提供完全数据保障的方案;
- AOF 文件会在操作过程中变得越来越大。比如,如果做一百次加法计算,最后只会在数据库里面得到最终的数值,但是在你的 AOF 里面会存在 100 次记录,其中 99 条记录对最终的结果是无用的;但 Redis 支持在不影响服务的前提下在后台重构 AOF 文件,让文件得以整理变小。
- 可以同时使用这两种方式,redis 默认优先加载 aof 文件(aof 数据最完整);
主从复制
读写分离
通过持久化功能,Redis 保证了即使在服务器重启的情况下也不会丢失(或少量丢失)数据,但是由于数据是存储在一台服务器上的,如果这台服务器出现故障,比如硬盘坏了,也会导致数据丢失。
为了避免单点故障,需要将数据复制多份部署在多台不同的服务器上,即使有一台服务器出现故障其他服务器依然可以继续提供服务。
这就要求当一台服务器上的数据更新后,自动将更新的数据同步到其他服务器上,通过 Redis 的主从复制实现。
Redis 提供了复制(replication)功能来自动实现多台 redis 服务器的数据同步(每天 19点 新闻联播,基本从 cctv1-8,各大卫视都会播放)
可以通过部署多台 redis,并在配置文件中指定这几台 redis 之间的主从关系,主负责写入数据,同时把写入的数据实时同步到从机器,这种模式叫做主从复制,即 master/slave,并且 redis 默认 master 用于写,slave 用于读,向 slave 写数据会导致错误。
主从复制实现
方式一:修改配置文件,启动时,服务器读取配置文件,并自动成为指定服务器的从服务器,从而构成主从复制的关系。
方式二:./redis-server --slaveof <master-ip> <master-port>
,在启动 redis 时指定当前服务成为某个主 redis 服务的从 slave,配置中需开启后台启动:daemonize yes。
方式一的实现
注意:停止正在运行的 redis 服务
- 将原有的 redis.conf 文件拷贝三份,分别命名为 redis6380.conf,redis6382.conf,redis6384.conf。
ps:vi 后 :%d 可以清空文件内容。
root# cp redis.conf redis6380.conf
root# > redis6380.conf
root# cat redis6380.conf
root# cp redis6380.conf redis6382.conf
root# cp redis6380.conf redis6384.conf
root# ls redis6*.conf
- 编辑 Master 配置文件
redis6380.conf 作为 Master 配置文件,在空文件中加入如下内容:
include /usr/local/redis-3.2.9/redis.conf
daemonize yes
port 6380
pidfile /var/run/redis_6380.pid
logfile 6380.log
dbfilename dump6380.rdb
配置项说明:
include
:参数是 redis.conf 文件的绝对路径(自行根据自己的文件路径设置),表示包含原来的配置文件内容。daemonize
:yes 表示后台启动应用,相当于./redis-server &
的作用。port
:自定义的端口号pidfile
:自定义的文件,表示当前程序的 pid,进程 id。logfile
:日志文件名。dbfilename
:持久化的 rdb 文件名。
- 编辑 Slave 配置文件
redis6382.conf 与 redis6384.conf 作为 Slave 配置文件,在空文件中加入如下内容:
redis6382.conf:
include /usr/local/redis-3.2.9/redis.conf
daemonize yes
port 6382
pidfile /var/run/redis_6382.pid
logfile 6382.log
dbfilename dump6382.rdb
slaveof 192.168.xxx.xxx 6380
配置项说明:
slaveof
:表示当前 redis 是谁的从。当前是 192.168.xxx.xxx 端口 6380 这个 Master 的从。
redis6384.conf:
include /usr/local/redis-3.2.9/redis.conf
daemonize yes
port 6384
pidfile /var/run/redis_6384.pid
logfile 6384.log
dbfilename dump6384.rdb
slaveof 192.168.xxx.xxx 6380
- 启动服务器 Master/Slave 都启动
启动方式:./redis-server 配置文件 &
启动 Redis,并查看启动进程:ps -ef | grep redis
- 查看配置后的服务信息
命令:
- redis 客户端使用指定端口连接 Redis 服务器:
redis-cli -h 192.168.xxx.xxx -p 端口
- 查看服务器信息:
info replication
向主 Master 写入数据
在从 Slave 读取数据,Slave 写入数据会报错,做到读(Slave)写(Master)分离。
容灾处理
��� Master 服务出现故障,需手动将 slave 中的一个提升为 master,剩下的 slave 挂至新的 master 上(冷处理:机器挂掉了,再处理)
命令:
slaveof no one
:将一台 Slave 服务器提升为 Master(提升某 slave 为 master)slaveof 192.168.xxx.xxx 63xx
:将 slave 挂至新的 master 上。
执行步骤:
- 将 Master:6380 停止(模拟挂掉)
- 选择一个 Slave 提��到 Master
这里是将端口 6382 的 Slave 提升到 Master
- 将其他 Slave 挂到新的 Master
这里是将端口 6384 的 Slave 挂到新的 Master 上
查看新的主从关系:
- 将原来的服务器重新添加到主从结构中
6380 的服务器修改后重新工作,需要把它添加到现有的 Master/Slave 中
- 首先启动 6380 的 redis 服务
- 然后连接到 6380 端口的 redis 命令行客户端
- 最后执行
slaveof 192.168.xxx.xxx 6382
将当前服务挂到 Master 上
- 查看新的 Master 信息
6382 执行: info replication
现在的 Master/Slaver 关系是:
Master:6382
Slave:6380、6384
总结:
- 不修改配置文件启动或者不配置启动默认都是主 master
- 进入客户端需指定端口:
./redis-cli -p 6380
info replication
查看 redis 服务器所处角色- 一个 master 可以有多个 slave
- slave 下线,读请求的处理性能下降;master 下线,写请求无法执行。
- 当 master 发生故障,需手动将其中一台 slave 使用
slaveof no one
命令提升为 master,其它 slave 执行slaveof 192.168.xxx.xxx xxxx
命令指向这个新的 master,从新的 master 处同步数据。
主从复制模式的故障转移需要手动操作,要实现自动化处理,这就需要 Sentinel 哨兵,实现故障自动转移。
高可用 Sentinel 哨兵
Sentinel 哨兵是 redis 官方提供的高可用方案,可以用它来监控多个 Redis 服务实例的运行情况。
Redis Sentinel 是一个运行在特殊模式下的 Redis 服务器。
Redis Sentinel 是在多个 Sentinel 进程环境下互相协作工作的。
Sentinel 系统有三个主要任务:
监控:Sentinel 不断的检查主服务器和从服务器是否按照预期正常工作。
提醒:被监控的 Redis 出现问题时,Sentinel 会通知管理员或其他应用程序。
自动故障转移:监控的主 Redis 不能正常工作,Sentinel 会开始进行故障迁移操作,将一个从服务器升级新的主服务器,让其他从服务器挂到新的主服务器,同时向客户端提供新的主服务器地址。
Sentinel 配置
- 复制三份 sentinel.conf 文件:
root# cp sentinel.conf sentinel26380.conf
root# cp sentinel.conf sentinel26382.conf
root# cp sentinel.conf sentinel26384.conf
- 修改 sentinel 配置文件中的端口
默认端口为:26379
sentinel26380.conf:port 26380
sentinel26382.conf:port 26382
sentinel26384.conf:port 26384
- 修改 sentinel 配置文件中的 ip、redis-port、quorum
sentinel monitor <master-name> <ip> <redis-port> <quorum>
默认为:sentinel monitor mymaster 127.0.0.1 6379 2
修改监控的 master 为:
sentinel26380.conf:sentinel monitor mymaster 127.0.0.1 6380 2
sentinel26382.conf:sentinel monitor mymaster 127.0.0.1 6380 2
sentinel26384.conf:sentinel monitor mymaster 127.0.0.1 6380 2
启动主从 master/slave redis
启动 sentinel
执行
info replication
确定 master 然后执行shutdown
等一会,sentinel 起作用,查看新的 master
新的 redis 加入 sentinel 系统,自动加入 master
监控:
- Sentinel 会不断检查 Master 和 Slave 是否正常
- 如果 Sentinel 挂了,就无法监控,所以需要多个哨兵,组成 Sentinel 网络,一个健康的 Sentinel 至少有3个 Sentinel 应用。彼此在独立的物理机器或虚拟机。
- 监控同一个 Master 的 Sentinel 会自动连接,组成一个分布式的 Sentinel 网络,互相通信并交换彼此关于被监控服务器的信息。
- 当一个 Sentinel 认为被监控的服务器已经下线时,它会向网络中的其它 Sentinel 进行确认,判断该服务器是否真的已经下线。
- 如果下线的服务器为主服务器,那么 Sentinel 网络将对下线主服务器进行自动故障转移,通过将下线主服务器的某个从服务器提升为新的主服务器,并让其从服务器转移到新的主服务器下,以此来让系统重新回到正常状态。
- 下线的旧主服务器重新上线,Sentinel 会让它成为从服务器,挂到新的主服务器下。
- 总结
主从复制,解决了读请求的分担,从节点下线,会使得读请求能力有所下降,Master 下线,写请求无法执行
Sentinel 会在 Master 下线后自动执行故障转移操作,提升一台 Slave 为 Master,并让其它 Slave 成为新Master 的 Slave。
安全设置
设置密码
访问 Redis 默认是没有密码的,这样不安全,任意用户都可以访问。可以启用使用密码才能访问 Redis。 设置Redis 的访问密码,修改 redis.conf 中这行 requirepass 密码。密码要比较复杂,不容易破解,而且需要定期修改。因为 redis 速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行 150K 次的密码尝试,需要指定非常非常强大的密码来防止暴力破解。
开启访问密码设置
redis.conf 文件中去掉 requirepass 注释,在 requirepass 空格后面填写密码
redis.conf:requirepass 123456
查看修改结果:cat redis.conf | grep requirepass
访问有密码的 Redis
如果 redis 已经启动,关闭后重新启动。
访问有密码的 redis 两种方式:
- 方式一:连接 redis 命令行客户端后,使用命令
auth password
,命令执行成功后可以正常使用 redis,否则会出现错误关于 AUTH 的错误。 - 方式二:连接 redis 命令行客户端时,使用命令
./redis-cli -h ip -p port -a password
绑定 IP
修改 redis.conf 文件,把 # bind 127.0.0.1
前面的注释 #
号去掉,然后把 127.0.0.1 改成允许访问你 redis 服务器的 ip 地址,表示只允许该 ip 进行访问。多个 ip 使用空格分隔。
修改默认端口
修改 redis 的端口,这一点很重要,使用默认的端口很危险,redis.conf 中修改 port 6379 将其修改为自己指定的端口(可随意),端口 1024 是保留给操作系统使用的。用户可以使用的范围是 1024-65535
使用 -p
参数指定端口,例如:./redis-cli -p 新设置端口
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: