Redis操作
文章目录
一、Redis数据类型操作命令
1、字符串类型(string)
(1)基本命令
先测试能连接到 redis 服务器,返回 PONG,表示 redis 服务运行正常
A、set
将字符串值 value 设置到 key 中
语法:set key value
查看已经插入的 key
向已经存在的 key 设置新的 value,会覆盖原来的值
B、get
获取 key 中设置的字符串值
语法:get key
例如:获取 username 这个key 对应的 value
C、incr
将 key 中储存的数字值加 1,如果 key 不存在,则 key 的值先被初始化为 0 再执行 incr 操作(只能对数字类型的数据操作)
语法:incr key
例1:操作 key 值增加 1
例2:对非数字的值操作是不行的
D、decr
将 key 中储存的数字值减 1,如果 key 不存在,那么 key 的值先被初始化为 0 再执行 decr 操作(只能对数字类型的数据操作)
语法:decr key
E、append
语法:append key value
说明:如果 key 存在,则将 value 追加到 key 原来旧值的末尾。如果 key 不存在,则将 key 设置值为 value
返回值:追加字符串之后的总长度
例1:追加内容到存在的 key
例2:追加到不存在的 key,同 set key value
(2)常用命令
A、strlen
语法:strlen key
说明:返回 key 所储存的字符串值的长度
返回值:
- 如果 key 存在,返回字符串值的长度
- key 不存在, 返回 0
例1:计算存在 key 的字符串长度
设置中文 set k1 中文长度,按字符个数计算
例2:计算不存在的 key
B、getrange
语法:getrange key start end
作用:获取 key 中字符串值从 start 开始到 end 结束的子字符串,包括 start 和 end,负数表示从字符串的末尾开始, -1 表示最后一个字符
返回值:截取的子字符串
使用的字符串 key:index,value: 20hello
例:截取从 2 到 -1 的字符
C、setrange
语法:setrange key offset value
说明:用 value 覆盖(替换)key 的存储的值从 offset 开始,不存在的 key 做空白字符串
返回值:修改后的字符串的长度
例:替换给定的字符串
D、mset
语法:mset key value [key value…]
说明:同时设置一个或多个 key-value 对
返回值:OK
例:一 次设置多个 key,value
E、mget
语法:mget key [key …]
作用:获取所有(一个或多个)给定 key 的值
返回值:包含所有 key 的列表
例1:返回多个 key 的存储值
例2:返回不存在的 key
2、哈希类型hash
redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
(1)基本命令
A、hset
语法:hset hash 表的 key field value
作用:将哈希表 key 中的域 field 的值设为 value ,如果 key 不存在,则新建 hash 表,行赋值,如果有 field,则覆盖值。
返回值:
- 如果 field 是 hash 表中新 field,且设置值成功,返回 1
- 如果 field 已经存在,旧值覆盖新值,返回 0
例1:新的 field
例2:覆盖旧的 field
B、hget
语法:hget key field
作用:获取哈希表 key 中给定域 field 的值
返回值:field 域的值,如果 key 不存在或者 field 不存在返回 nil
例1:获取存在 key 值的某个域的值
例2:获取不存在的 field
C、hmset
语法:hmset key field value [field vale…]
说明:同时将多个 field-value(域值)设置到哈希表 key 中,此命令会覆盖已经存在的 field。hash 表 key 不存在,创建空的 hash 表,执行 hmset。
返回值:设置成功返回 ok,如 果失败返回一个错误
例:同时设置多个 field-value
使用 redis-desktop- manager工具查看 hash 表 website 的数据结构
D、hmget
语法:hmget key field [field…]
作用:获取哈希表 key 中一个或多个给定域的值
返回值:返回和 field 顺序对应的值,如果 field 不存在,返回 nil
例:获取多个 field 的值
E、hgetall
语法:hgetall key
作用:获取哈希表 key 中所有的域和值
返回值:以列表形式返回 hash 中域和域的值,key 不存在,返回空 hash
例1:返回 key 对应的所有域和值
F、hdel
语法:hdelkey field [field…]
作用:删除哈希表 key 中的一个或多个指定域 field,不存在 field 直接忽略
返回值:成功删除的 field 的数量
例:删除指定的 field
(2)常用命令
A、hkeys
语法:hkeys key
作用:查看哈希表 key 中的所有 field 域
返回值:包含所有 field 的列表,key 不存在返回空列表
例:查看 website 所有的域名称
B、hvals
语法:hvals key
作用:返回哈希表中所有域的值
返回值:包含哈希表所有域值的列表,key 不存在返回空列表
例:显示 website 哈希表所有域的值
C、hexists
语法:hexists key field
作用:查看哈希表 key 中,给定域 field 是否存在
返回值:如果 field 存在,返回 1,其他返回 0
例:查看存在 key 中 field 域是否存在
3、列表list
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
(1)基本命令
A、Ipush
语法:lpush key value [value…]
作用:将一个或多个值 value 插入到列表 key 的表头(最左边),从左边开始加入值,从左到右的顺序依次插入到表头
返回值:数字,新列表的长度
例:将 a,b,c 插入到 mylist 列表类型
在 redis-desktop- manager 显示
B、rpush
语法:rpush key value [value…]
作用:将一个或多个值 value 插入到列表 key 的表尾(最右边),各个 value 值按从左到右的顺序依次插入到表尾
返回值:数字,新列表的长度
例:将 a,b,c 插入到 mylist2 列表类型
在 redis-desktop- manager 显示
C、 lrange
语法:lrange key start stop
作用:获取列表 key 中指定区间内的元素,0 表示列表的第一个元素,以1表示列表的第二个元素;start,stop 是列表的下标值,也可以是负数的下标,-1 表示列表的最后一个元素,-2 表示列表的倒数第二个元素,以此类推。start ,stop 超出列表的范围不会出现错误。
返回值:指定区间的列表
例:返回列表的 3 到 -1 的内容
D、lindex
语法:lindex key index
作用:获取列表 key 中下标为指定 index 的元素,列表元素不删除,只是查询。0 表示列表的第一个元素,以1表示列表的第二个元素;start,stop 是列表的下标值,也可以是负数的下标,-1 表示列表的最后一个元素,-2 表示列表的倒数第二个元素,以此类推。
返回值:指定下标的元素;index 不在列表范围,返回 nil
例:返回下标是 0 的元素
E、llen
语法:llen key
作用:获取列表 key 的长度
返回值:数值,列表的长度;key 不存在返回 0
例:显示存在 key 的列表元素的个数
(2)常用命令
A、Irem
语法:Irem key count value
作用:根据参数 count 的值,移除列表中与参数 value 相等的元素,count > 0 ,从列表的左侧向右开始移除;couunt < 0从列表的尾部开始移除;count = 0 移除表中所与 value 相等的值
返回值:数值,移除的元素个数
例:删除 1 个相同的列表元素
B、Iset
语法:Iset key index value
作用:将列表 key 下标为 index 的元素的值设置为 value。
返回值:设置成功返回 ok;key 不存在或者 index 超出范围返回错误信息
例:设置下标 1 的 value 为 A
C、linsert
语法:linsert key BEFORE|ALFTER pivot value
作用:将值 value 插入到列表 key 当中位于值 pivot 之前或之后的位置。key 不存在,pivot 不在列表中,不执行任何操作
返回值:命令执行成功,返回新列表的长度。没有找到 pivot 返回 -1,key 不存在返回
例:修改列表 mylist,在值 A 之后加入 B
4、集合类型set
redis 的 Set 是 string 类型的无序集合,集合成员是唯一的, 即集合中不能出现重复的数据。
(1)基本命令
A、sadd
语法:sadd key member [member…]
作用:将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略,不会再加入
返回值:加入到集合的新元素的个数。不包括被忽略的元素
例:添加多个元素
B、smembers
语法:smembers key
作用:获取集合 key 中的所有成员元素,不存在的 key 视为空集合
例:查看集合的所有元素
C、sismember
语法:sismember key member
作用:判断 member 元素是否是集合 key 的成员
返回值:member 是集合成员返回 1,其他返回 0
例:检查元素是否存在集合中
D、scard
语法:scard key
作用:获取集合里面的元素个数
返回值:数字,key 的元素个数;其他情况返回 0
例:统计集合的大小
E、srem
语法:srem key member [member…]
作用:删除集合 key 中的一个或多个 member 元素,不存在的元素被忽略
返回值:数字,成功删除的元素个数,不包括被忽略的元素
例:删除存在的两个元素,返回数字2
(2)常用命令
A、srandmember
语法:srandmember key [count]
作用:只提供 key, 随机返回集合中一个元素,元素不删除,依然在集合中;提供了 count 时,count 正数,返回包含 count 个数元素的集合,集合元素各不相同。count 是负数,返回一个 count 绝对值的长度的集合,集合中元素可能会重复多次。
返回值:一个元素;多个元素的集合
例:随机显示集合的两个元素
B、spop
语法:spop key [count]
作用:随机从集合中删除一个元素,count 是删除的元素个数
返回值:被删除的元素,key 不存在或空集合返回 nil
例:随机从集合删除一个元素
5、有序集合类型zset(sorted set)
redis 有序集合 zset 和集合 set 一样也是 string 类型元素的集合,且不允许重复的成员。不同的是 zset 的每个元素都会关联一个分数(分数可以重复),redis 通过分数来为集合中的成员进行从小到大的排序。
(1)基本命令
A、zadd
语法:zadd key score member [score member…]
作用:将一个或多个 member 元素及其 score 值加入到有序集合key 中,如果 member存在集合中,则更新值;score 可以是整数或浮点数
返回值:数字,新添加的元素个数
例:创建保存学生成绩的集合
在 redis-desktop- manager 显示
B、zrange
语法:zrange key start stop [WITHSCORES]
作用:查询有序集合,指定区间的内的元素。集合成员按 score 值从小到大来排序。start,stop 都是从 0 开始。0 是第一个元素,1 是第二个元素,依次类推。以 -1表示最后一个成员,-2 表示倒数第二个成员。WITHSCORES 选项让 score 和 value 一同返回。
返回值:自定区间的成员集合
例1:显示集合的全部元素,不显示 score,不使用 WITHSCORES
例2:显示集合的全部元素,并使用 WITHSCORES
C、 zrevrange
语法:zrevrange key start stop [WITHSCORES]
作用:返回有序集 key 中, 指定区间内的成员。其中成员的位置按 score 值递减(从大到小)来排列。其它同 zrange 命令。
返回值:自定区间的成员集合
例:成绩榜
D、zrem
语法:zrem key member [member…]
作用:删除有序集合 key 中的一个或多个成员,不存在的成员被忽略
返回值:被成功删除的成员数量,不包括被忽略的成员
例:删除指定一个成员 ww
E、zcard
语法:zcard key
作用:获取有序集 key 的元素成员的个数
返回值:key 存在返回集合元素的个数,key 不存在,返回 0
例:查询集合的元素个数
(2)常用命令
A、zrangebyscore
语法:zrangebyscore key min max [WITHSCORES ] [LIMIT offset count]
作用:
- 获取有序集 key 中,所有 score 值介于 min 和 max 之间(包括 min 和 max)的成员,有序成员是按递增(从小到大)排序。
- min,max 是包括在内,使用符号 “(” 表示不包括。min,max 可以使用 -inf,+inf 表示最小和最大
- limit 用来限制返回结果的数量和区间
- withscores 显示 score 和 value
返回值:指定区间的集合数据
注意:[LIMIT offset count] 是做分页处理,用法同 mysql 的分页查询一致
例1:查询工资 2000 - 3000 的员工
例2:查询工资 2000 - 4500 的员工(不包含)
例3:查看工资小于 3000 的员工
B、zrevrangebyscore
语法:zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count]
作用:返回有序集 key 中,score 值介于 max 和 min 之间(默认包括等于 max 或 min)的所有的成员。 有序集成员按 score 值递减(从大到小)的次序排列。其他同zrangebyscore
例:查询工资最高到 3000 之间的员工
C、zcount
语法:zcount key min max
作用:返回有序集 key 中,score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max)的成员的数量
例:求工资在 3000 - 5000 的员工数量
二、高级话题
1、Redis事务
(1)什么是事务
事务是指一系列操作步骤,,这一系列的操作步骤,要么完全地执行,要么完全地不执行。
Redis 中的事务(transaction)是一组命令的集合,至少是两个或两个以上的命令,redid 事务保证这些命令被执行时中间不会被任何其他操作打断。
(2)事务操作的命令
A、multi
语法:multi
作用:标记一个事务的开始。事务内的多条命令会按照先后顺序被放进一个队列当中
返回值:总是返回 ok
B、exec
语法:exec
作用:执行所有事务块内的命令
返回值:事务内的所有执行语句内容,事务被打断(影响)返回 nil
C、discard
语法:discard
作用:取消事务,放弃执行事务块内的所有命令
返回值:总是返回 ok
D、watch
语法:watch key [key …]
作用:监视一个(或多个)key,如果在事务执行之前这个(或这些)key 被其他命令所改动,那么事务将被打断
返回值:总是返回 ok
E、unwatch
语法:unwatch
作用:取消 WATCH 命令对所有 key 的监视。如果在执行 WATCH 命令之后,EXEC 命令或 DISCARD 命令先被执行了的话,那么就不需要再执行 UNWATCH 了
返回值:总是返回 ok
(3)事务的实现
A、正常执行事务
事务的执行步骤:首先开启事务,其次向事务队列中加入命令,最后执行事务提交
例:事务的执行
- multi:用 multi 命令告诉 Redis,接下来要执行的命令先不要执行,而是把它们暂时存起来(开启事务)
- sadd works jack:第一条命令进入等待队列(命令入队)
- sadd works rose:第二条命令进入等待队列 (命令入队)
- exce:告知 redis 执行前面发送的两条命令(提交事务)
B、事务执行exec之前,入队命令错误(语法错误;严重错误导致服务器不能正常工作(例如内存不足)),放弃事务
执行事务步骤:
- multi:正常命令
- set key value:正常命令
- incr:命令语法错误
- exec:无法执行事务, 那么第一条正确的命令也不会执行,所以 key 的值不会设置成功
C、事务执行exec命令后,执行队列命令,命令执行错误,事务提交
执行步骤:
- multi:正常命令
- set username zhangsan:正常命令
- Ipop username:正常命令, 语法没有错误,执行命令时才会有错误
- exec:正常执行,发现错误可以在事务提交前放弃事务,执行 discard
D、放弃事务
执行步骤:
- multi:开启事务
- set age 10:命令入队
- discard:放弃事务,则命令队列不会被执行
E、Redis的watch机制
Redis的WATCH机制
WATCH机制原理:
- WATCH机制:使用 WATCH 监视一个或多个 key,跟踪 key 的 value 修改情况,如果有 key 的 value 值在事务 EXEC 执行之前被修改了,整个事务被取消。EXEC 返回提示信息,表示事务已经失败
- WATCH 机制使的事务 EXEC 变的有条件,事务只有在被 WATCH 的 key 没有修改的前提下才能执行。不满足条件,事务被取消。使用 WATCH 监视了一个带过期时间的键,那么即使这个键过期了,事务仍然可以正常执行
- 大多数情况下,不同的客户端会访问不同的键,相互同时竞争同一 key 的情况一般都很少,乐观锁能够以很好的性能解决数据冲突的问题
WATCh的事例
- 在A客户端设置 key:str.lp登录人数为 10
- 在A客户端监视 key:str.lp
- 在A客户端开启事务:multi
- 在A客户端修改 str.lp 的值为 11
- 在B客户端修改 str.lp 的值为 15
- 在A客户端执行事务:exec
- 在A客户端查看 str.lp 值,A客户端执行的事务没有提交,因为 WATCH 的 str.lp 的值已经被修改了,所以放弃事务
2、持久化
(1)持久化概述
持久化可以理解为存储,就是将数据存储到一个不会丢失的地方,如果把数据放在内存中,电脑关闭或重启数据就会丢失,所以放在内存中的数据不是持久化的,而放在磁盘就算是一种持久化。
Redis 的数据存储在内存中,内存是瞬时的,如果 linux 宕机或重启,又或者 Redis 崩溃或重启,所有的内存数据都会丢失,为解决这个问题,Redis 提供两种机制对数据进行持久化存储,便于发生故障后能迅速恢复数据。
(2)持久化方式
A、RDB方式
什么是RDB方式?
Redis Database(RDB), 就是在指定的时间间隔内将内存中的数据集快照写入磁盘,数据恢复时将快照文件直接再读到内存。
RDB 保存了在某个时间点的数据集(全部数据)。存储在一个二进制文件中,只有一个文件。默认是 dump.rdb。 RDB 技术非常适合做备份,可以保存最近一个小时,一天,一个月的全部数据。保存数据是在单独的进程中写文件,不影响 Redis 的正常使用。RDB 恢复数据时比其他AOF速度快。
如何实现?
RDB 方式的数据持久化,仅需在 redis.conf 文件中配置即可,默认配置是启用的。
在配置文件 redis.conf 中搜索 SNAPSHOTTING,查找在注释开始和结束之间的关于 RDB 的配置说明。配 SNAPSHOTTING 置地方有三处。
-
配置执行 RDB 生成快照文件的时间策略
- 对 Redis 进行设置,让它在 “ N 秒内数据集至少有M个 key 改动 ” 这一条件被满足时,自动保存一次数据集。
- 配置格式:save ,如:save 600 10
-
dbfilename:设置 RDB 的文件名,默认文件名为 dump.rdb
-
dir:指定 RDB 文件的存储位置,默认是 ./ 当前目录
配置步骤:
-
查看 ps-ef | grep redis,如果 redis 服务启动,先停止
-
执行:vim redis.conf,修改文件
- 修改 RDB 生成快照文件的时间
- 设置 RDB 的文件名
- 指定 RDB 文件的存储位置
- 修改 RDB 生成快照文件的时间
总结:
- 优点:由于存储的是数据快照文件,恢复数据很方便,也比较快
- 缺点:
- 会丢失最后一次快照以后更改的数据。如果你的应用能容忍一定数据的丢失,那么使用 RDB 是不错的选择;如果你不能容忍一定数据的丢失,使用 RDB 就不是一个很好的选择
- 由于需要经常操作磁盘,RDB 会分出一个子进程。如果你的 redis 数据库很大的话,子进程占用比较多的时间,并且可能会影响Redis 暂停服务一段时间(millisecond级别),如果你的数据库超级大并且你的服务器 CPU 比较弱,有可能是会达到一秒
B、AOF方式
什么是AOF方式
Append-only File(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。当 ao f文件大于 64M时,开始整理 aop 文件, 去掉无用的操作命令。缩小 aop 文件。
配置步骤:
-
停止运行的 redis,备份要修改的 redis.conf 文件
-
查看 redis 安装目录 /src 下有无 .aof 文件。默认是在 redis 的当前目录
-
编辑 redis.conf
- 设置 appendonly 为 yes 即可
- 配置向 aof 文件写命令数据的策略
- 设置 appendonly 为 yes 即可
3、主从复制
(1)主从复制-读写分离
通过持久化功能,Redis 保证了即使在服务器重启的情况下也不会丢失(或少量丢失)数据,但是由于数据是存储在一台服务器上的,如果这台服务器出现故障,比如硬盘坏了,也会导致数据丢失。
为了避免单点故障,我们需要将数据复制多份部署在多台不同的服务器上,即使有一台服务器出现故障其他服务器依然可以继续提供服务。
这就要求当一台服务器上的数据更新后,自动将更新的数据同步到其他服务器上,那该怎么实现呢?Redis 的主从复制。
Redis 提供了复制(replication)功能来自动实现多台 redis 服务器的数据同步。
我们可以通过部署多台 redis, 并在配置文件中指定这几台 redis 之间的主从关系,主负责写入数据,同时把写入的数据实时同步到从机器,这种模式叫做主从复制,即 master/slave,并且 redis 默认 master 用于写,slave 用于读,向 slave 写数据会导致错误。
A、Redis主从复制实现(master/salve)
- 方式1:修改配置文件,启动时,服务器读取配置文件,并自动成为指定服务器的从服务器,从而构成主从复制的关系
- 方式2:./redis-server --slaveof , 在启动 redis 时指定当前服务成为某个主 Redis 服务的从 Slave
方式1 的实现步骤:
模拟多 Reids 服务器,在一台已经安装 Redis 的机器上,运行多个 Redis 应用模拟多个 Reids 服务器。一个 Master,两个 Slave。
-
新建三个 Redis 的配置文件
-
如果 Redis 启动,先停止。
-
作为 Master 的 Redis 端口是6380
-
作为 Slaver 的 Redis 端口分别是 6382,6384
-
从原有的 redis.conf 拷贝三份,分别命名为 redis6380.conf,redis6382.conf,redis6384.conf
-
-
编辑 Master 配置文件
-
编辑 Master 的配置文件 redis6380.conf:在空文件加入如下内容
include /usr/local/redis-6.0.5/redis.conf daemonize yes port 6380 pidfile /var/run/redis_6380.pid logfile 6380.log dbfilename dump6380.rdb
[
- 配置项说明:
- include:包含原来的配置文件内容。/usr/local/redis-6.0.5/redis.conf 按照自己的目录设置
- daemonize:yes 后台启动应用,相当于./redis-server &,& 的作用
- port:自定义的端口号
- pidfile:自定义的文件,表示当前程序的 pid,进程 id
- logfile:日志文件名
- dbfilename:持久化的 rdb 文件名
-
-
编辑 Slave 配置文件
-
编辑 Slave 的配置文件 redis6382.conf 和 redis6384.conf:在空文件加入如下内容
include /usr/local/redis-6.0.5/redis.conf daemonize yes port 6382 pidfile /var/run/redis_6382.pid logfile 6382.log dbfilename dump6382.rdb slaveof 127.0.0.1 6380
[
- 配置项说明:
- slaveof:表示当前 Redis 是谁的从。当前是 127.0.0.0 端口 6380 这个 Master 的从
-
-
启动服务器 Master/Slave 都启动
- 启动方式 ./redis-server 配置文件
- 启动主客户端,查看 Master 信息
- 启动从客户端,,查看 Slave 信息
- 启动方式 ./redis-server 配置文件
B、容灾处理
当 Master 服务出现故障,需手动将 slave 中的一个提升为 master,剩下的 slave 挂至新的 master 上(冷处理:机器挂掉了,再处理)
命令:
- slaveof no one:将一台 slave 服务器提升为 Master(提升某 slave 为 master)
- slaveof 127.0.0.1 6382:将 slave 挂至新的 master 上
执行步骤:
-
将 Master:6380停止(模拟挂掉)
-
选择一个 Slave 升到 Master
-
将其他 Slave 挂到新的 Master
-
原来的服务器重新添加到主从结构中
- 6380的服务器修改后,重新工作,需要把它添加到现有的 Master/Slave 中,先启动 6380 的 Redis 服务
- 连接到 6380 端口,查看信息
- 将本服务器挂到新的 Master,并查看信息
- 6380的服务器修改后,重新工作,需要把它添加到现有的 Master/Slave 中,先启动 6380 的 Redis 服务
-
查看新的 Master 信息
(2)高可用Sentinel哨兵
Sentinel 哨兵是 redis 官方提供的高可用方案,可以用它来监控多个 Redis 服务实例的运行情况。Redis Sentinel 是一个运行在特殊模式下的 Redis 服务器。Redis Sentinel 是在多个 Sentinel 进程环境下互相协作工作的。
Sentinel 系统有三个主要任务:
- 监控:Sentinel 不断的检查主服务和从服务器是否按照预期正常工作
- 提醒:被监控的 Redis 出现问题时,Sentinel 会通知管理员或其他应用程序
- 自动故障转移:监控的主 Redis 不能正常工作,Sentinel 会开始进行故障迁移操作。将一个从服务器升级新的主服务器。让其他从服 务器挂到新的主服务器。同时向客户端提供新的主服务器地址
A、Sentinel配置
-
Sentinel 配置文件
- 复制三份 sentinel.conf 文件
- Sentinel 系统默认 port 是26379。三个配置 port 分别设置为 26380,26382,26384。三个文件分别命名:sentinel26380.conf、sentinel26382.conf、sentinel26384.conf
- 复制三份 sentinel.conf 文件
B、三份sentinel配置文件修改
-
修改 port 26380、port26382、port26384
-
修改 sentinel monitor mymaster 127.0.0.1 6380 2
格式: sentinel monitor <name> <masterIP> <masterPort> <Quorum 投票数>
Sentinel 监控主(Master)Redis,Sentinel 根据 Master 的配置自动发现 Master 的 Slave,Sentinel 默认端口号为 26379。
-
sentinel26380.conf
- 修改 port
- 修改监控的 master 地址
- 修改 port
-
sentinel26382.conf、sentinel26384.conf的修改同上一致
C、启动主从(Master/Slaver)
D、启动Sentinel
redis 安装时 make 编译后就产生了 redis-sentinel 程序文件,可以在一个 redis 中运行多个 sentinel 进程。
执行以下三条命令,将创建三个监视主服务器的 Sentinel 实例:
- ./redis-sentinel …/sentinel26380.conf
- ./redis-sentinel …/sentinel26382.conf
- ./redis-sentinel …/sentinel26384.conf
在 XShell 开启三个窗口分别执行:
E、主Redis不能工作
让 Master 的 Redis 停止服务,执行 shutdown。
先执行 info replication 确认 Master 的 Redis,再执行 shutdown
F、Sentinel的起作用
当 Master 的 Redis 停止服务后,Sentinel 会自动进行选举,随机从剩下的两个从服务器选出一个成为新的 Master 。
查看主服务器6380端口的信息:
G、新的Redis加入Sentinel
当 redis 修复好之后,再次启动
H、监控
Sentinel 会自行进行监视,把修复好的 redis 添加到主服务器中。
查看主服务器6380端口的信息:
4、安全设置
(1)设置密码
访问 Redis 默认是没有密码的,这样不安全,任意用户都可以访问。可以启用使用密码才能访问 Redis。设置 Redis 的访问密码,修改 redis.conf 中这行 requirepass 密码。密码要比较复杂,不容易破解,而且需要定期修改。因为 redis 速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行 150K 次的密码尝试,需要指定非常非常强大的密码来防止暴力破解。
A、开启访问密码设置
修改 redis.conf,使用 vim 命令。找到 requirepass 行去掉注释,requirepass 空格后就是密码。
例:设置访问密码是 123456,这是练习使用,生产环境要设置复杂密码
B、访问redis的两种方式
- 在使用 redis 客户端时,执行 ./redis-cli -a 123456 命令
- 在进入客户端后,执行 auth 123456 命令
(2)绑定ip
修改 redis.conf 文件,把 # bind 127.0.0.1 前面的注释 # 号去掉,然后把 127.0.0.1 改成允许访问你 redis 服务器的 ip 地址,表示只允许该 ip 进行访问。多个 ip 使用空格分隔。
例如:bind 192.168.1.100 192.168.2.10
(3)修改默认端口
修改 redis 的端口,这一点很重要,使用默认的端口很危险,redis.conf 中修改 port 6379,将其修改为自己指定的端口(可随意),端口 1024 是保留给操作系统使用的。用户可以使用的范围是 1024-65535。
使用 -p 参数指定端口,例如:./redis-cli -p 新设置端口
三、Jedis操作Redis
使用 Redis 官方推荐的 Jedis,在 java 应用中操作 Redis。Jedis 几乎涵盖了 Redis 的所有命令。操作 Redis 的命令在 Jedis 中以方法的形式出现。jedis 完全兼容 redis 2.8.x and 3.x.x
- Jedis 源码:https://github.com/xetorthio/jedis
- api文档:http://xetorthio.github.io/jedis/
- 下载:http://search.maven.org/,搜索 jedis
1、下载Jedis和Commons-Pool
(1)下载Jedis
浏览器打开:https://mvnrepository.com/artifact/redis.clients/jedis
(2)下载Commons-Pool
浏览器打开:https://mvnrepository.com/artifact/org.apache.commons/commons-pool2
2、Java应用使用Jedis准备之字符串(string)
(1)RedisString(写入字符串)
package cn.edu.huat.redis;
import redis.clients.jedis.Jedis;
import java.util.List;
public class RedisString {
public static void main(String[] args) {
/**
* 通过网络,访问Redis服务器:
* 1.修改redis .conf ,启动redis需要指定redis . conf的位置
* 2.关闭linux防火墙,或者让redis的端口通过防火墙。
*/
//创建Jedis对象,指定连接的redis服务器的ip,端口
/**
* String host: redis所在的linux服务器的ip
* int port: redis运行的端口号
*/
String host = "192.168.238.129";
int port = 6379;
Jedis jedis = new Jedis(host,port);
//设置访问密码
jedis.auth("123456");
//调用Jedis对象的方法,操作redis数据
jedis.set("break","热干面");
//获取key的值
String value = jedis.get("break");
System.out.println("break key = " + value);
//mset一次创建多个key-value
jedis.mset("lunch","猪排盖饭","dinner","牛排");
List<String> values = jedis.mget("break","lunch","dinner");
for (String val : values){
System.out.println(val);
}
}
}
(2)创建RedisUtil工具
package cn.edu.huat.redis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class RedisUtils {
private static JedisPool pool;
//创建JedisPool对象
public static JedisPool open(String ip,int port){
if (pool == null){
//创建JedisPool
JedisPoolConfig config = new JedisPoolConfig();
//给config设置连接池的参数
//设置最大的连接数,一个线程就是一个Jedis
config.setMaxTotal(20);
//设置最大的空闲数
config.setMaxIdle(2);
//设置检查项为true,表示从线程池中获取的对象一定是经过检查可用的
config.setTestOnBorrow(true);
//使用config对象创建JedisPool
/**
* poolConfig:配置器JedisPoolConfig
* host: redis所在的linux的ip
* port: redis的端口
* timeout :连接redis的超时,毫秒值
* password: redis的访问密码
*/
pool = new JedisPool(config,ip,port,6000,"123456");
}
return pool;
}
//关闭Pool对象
public static void close(){
if (pool != null){
pool.close();
}
}
}
(3)使用工具写入字符串
package cn.edu.huat.redis;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import java.util.List;
public class RedisStringPool {
public static void main(String[] args) {
/**
* 通过网络,访问Redis服务器:
* 1.修改redis .conf ,启动redis需要指定redis . conf的位置
* 2.关闭linux防火墙,或者让redis的端口通过防火墙。
*/
//创建Jedis对象,指定连接的redis服务器的ip,端口
/**
* String host: redis所在的linux服务器的ip
* int port: redis运行的端口号
*/
String host = "192.168.238.129";
int port = 6379;
//创建JedisPool对象,从JedisPool中获取Jedis
JedisPool pool = null;
Jedis jedis = null;
try {
pool = RedisUtils.open(host,port);
//从pool中获取Jedis
jedis = pool.getResource();
//调用Jedis对象的方法,操作redis数据
jedis.set("break","热干面2");
//获取key的值
String value = jedis.get("break");
System.out.println("break key = " + value);
jedis.mset("lunch","猪排盖饭2","dinner","牛排2");
List<String> values = jedis.mget("break","lunch","dinner");
for (String val : values){
System.out.println(val);
}
} finally {
//关闭Jedsi对象,把从pool中获取的Jedis放回到Pool,供其他对象使用
if (jedis != null){
jedis.close();
}
}
}
}