文章目录
- 一、NoSQL
- 二、Redis安装
- 三、Redis基础命令
- 1. 查看Redis服务是否正常 ping
- 2. 查看当前数据库中 key 的数目 dbsize
- 3. Redis的默认库
- 4. 切换库命令 select
- 5. 删除当前库的数据 flushdb
- 6. 删除所有库的数据 flushall
- 7. 退出当前 redis 连接 exit/quit
- 8. 关闭redis服务 shutdown
- 四、Redis的Key操作
- 1. 查看匹配的key keys
- 2. 判断 key 是否存在 exists
- 3. 设置 key 的生存时间 expire
- 4. 查看key的剩余生存时间 ttl
- 5. 查看 key 所存储值的数据类型 type
- 6. 删除存在的key del
- 五、字符串类型
- 1. 基本命令 (set/get/incr/decr/append)
- 2. key 所储存的字符串值的长度 strlen
- 3. 截取字符串 getrange
- 4. 替换 setrange
- 5. 批量设置 mset
- 6. 批量取值 mget
- 六、哈希类型 hash
- 1. 设定值 hset
- 2. 获取值 hget
- 3. 批量设置域 hmset
- 4. 批量获取域 hmget
- 5. 获取所有域和值 hgetall
- 6. 删除一个或多个域 hdel
- 7. 查看所有的域的field hkeys
- 8. 查看所有域的值 hvals
- 9. 查看给定域 field 是否存在 hexists
- 七、列表 list
- 1. 插入多个值 lpush
- 2. 获取多个值 rpush
- 3. 获取区间内的值 lrange
- 4. 获取指定下标的元素 lindex
- 5. 获取列表的长度 llen
- 6. 删除元素 lrem
- 7. 根据下标修改值 lset
- 8. 插入 linsert
- 八、集合类型 set
- 1. 增 sadd
- 2. 查 smembers
- 3. 判断是否存在 sismember
- 4. 获取个数 scard
- 5. 删除 srem
- 6. 随机返回一个元素 srandmember
- 7. 随机删除一个元素 spop
- 九、有序集合类型 zset (sorted set)
- 1. 添加 zadd
- 2. 区间查询,升序 zrange
- 3. 区间查询,降序 zrevrange
- 4. 删除 zrem
- 5. 获取成员个数 zcard
- 6. 根据分数范围获取元素(升序) zrangebyscore
- 7. 根据分数范围获取元素(降序) zrevrangebyscore
- 8. 根据分数范围获取元素数量 zcount
- 十、事务
- 十一、持久化
- 十二、主从复制
- 十三、其它设置
- 十四、Jedis
一、NoSQL
NoSQL = Not Only SQL(不仅仅是 SQL) ,也解释为 non-relational(非关系型数据库)。在 NoSQL 数据库中数据之间是无联系的,无关系的。数据的结构是松散的,可变的。
1. MySQL的瓶颈
- 无法应对每秒上万次的读写请求, 无法处理大量集中的高并发操作。关系型数据的是 IO 密集的应用。 硬盘 IO 也变为性能瓶颈
- 无法简单地通过增加硬件、服务节点来提高系统性能。数据整个存储在一个数据库中的。多个服务器没有很好的解决办法,来复制这些数据。
- 关系型数据库大多是收费的,对硬件的要求较高。软件和硬件的成本花费比重较大。
2. NoSQL的优势
- 大数据量,高性能
NoSQL 数据库都具有非常高的读写性能,尤其在大数据量下,同样表现优秀。这得益于它的无关系性,数据库的结构简单。 关系型数据库(例如 MySQL)使用查询缓存。这种查询缓存在更新数据后,缓存就是失效了。在频繁的数据读写交互应用中。缓存的性能不高。NoSQL 的缓存性能要高的多。 - 灵活的数据模型
NoSQL 无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。而在关系数据库里,增删字段是一件非常麻烦的事情。如果是非常大数据量的表,增加字段简直就是一个噩梦。 尤其在快速变化的市场环境中,用户的需求总是在不断变化的。 - 高可用
NoSQL 在不太影响性能的情况,就可以方便的实现高可用的架构。NoSQL 能很好的解决关系型数据库扩展性差的问题。 弥补了关系数据(比如 MySQL)在某些方面的不足,在某些方面能极大的节省开发成本和维护成本。MySQL 和 NoSQL 都有各自的特点和使用的应用场景,两者结合使用。让关系数据库关注在关系上, NoSQL 关注在存储上。 - 低成本
这是大多数分布式数据库共有的特点,因为主要都是开源软件,没有昂贵的 License 成本
3. NoSQL 的劣势
- 不支持标准的 SQL,没有公认的 NoSQL 标准
- 没有关系型数据库的约束,大多数也没有索引的概念
- 没有事务,不能依靠事务实现 ACID
- 没有丰富的数据类型(数值,日期,字符,二进制,大文本等)
更详细的介绍请戳这里(https://www.cnblogs.com/xrq730/p/11039384.html)
二、Redis安装
Remote Dictionary Server(Redis)是一个开源的使用 C 语言编写、支持网络、可基于内存亦可持久化的 Key-Value 数据库。Key 字符类型, 其值(value)可以是字符串(String),哈希(Map),列表(list),集合(sets) 和有序集合(sorted sets)等类型, 每种数据类型有自己的专属命令。 所以它通常也被称为数据结构服务器。
1. 解压
- 上传 redis-4.0.13.tar.gz 到 linux 系统。使用 Xftp 工具
- 解压 redis-4.0.13.tar.gz 到/usr/local 目录
2. 编译Redis源文件
Redis 是使用 c 语言编写的。 使用源文件安装方式,需要编译 c 源文件, 会使用 gcc 编译器。gcc 是 GNU compiler collection 的缩写,它是 Linux 下一个编译器集合(相当于 javac ), 是c 或 c++程序的编译器。
- 使用yum进行安装gcc 。
执行命令:yum -y install gcc
- 编译 redis 源文件
在解压后的 Redis 目录下执行(cd /usr/local/redis-4.0.13) make 命令:
如果 make 命令执行过程中出现错误:error: jemalloc/jemalloc.h: No such file or directorymake
解决方式执行下面的命令:make MALLOC=libc
- 编译成功的标志
- 查看make的编译结果
查看Redis的src目录:
3. 启动和关闭Redis服务
- 后台启动Redis:
在src目录下执行:./redis-server redis.conf配置文件路径 &
./redis-server ../redis.conf &
此时 ctrl + c 关闭窗口后,查看redis进程,依然存在。 - 关闭 Redis
使用 redis 客户端关闭,向服务器发出关闭命令
切换到 redis-4.0.13/src/ 目录,执行:
推荐使用这种方式, redis 先完成数据操作,然后再关闭。./redis-cli shutdown
4. Redis客户端
(1)命令行客户端
在 redis 安装目录/src下执行:
命令 | 说明 | 示例 |
---|---|---|
./redis-cli -h IP地址 -p 端口号 | 指定 IP 和端口连接 redis | ./redis-cli -h 127.0.0.1 -p 6379 |
./redis-cli | 直接连接 redis (默认 ip127.0.0.1,端口 6379) | ./redis-cli |
(2)远程连接Redis
连接Linux的Reids之前需要修改Redis服务器的配置信息。 Redis服务器有安全保护措施,默认只有本机(安装Redis的那台机器)能够访问。
修改redis主目录下的redis.conf
配置文件:(vim中使用 / 进行搜索)
- bind ip 绑定ip此行注释
- protected-mode yes 保护模式改为 no
注意:修改完之后要重启Redis服务,并且记得关闭防火墙
三、Redis基础命令
1. 查看Redis服务是否正常 ping
返回PONG,表示 redis 服务运行正常
2. 查看当前数据库中 key 的数目 dbsize
3. Redis的默认库
Redis 默认使用 16 个库, 从 0 到 15。 对数据库个数的修改,在 redis.conf 文件中修改databases 16
默认打开的是第0个数据库
4. 切换库命令 select
使用其他数据库, 命令是 select index
5. 删除当前库的数据 flushdb
6. 删除所有库的数据 flushall
7. 退出当前 redis 连接 exit/quit
8. 关闭redis服务 shutdown
四、Redis的Key操作
1. 查看匹配的key keys
语法: keys pattern
作用:查找当前库中所有符合模式 pattern 的 key. pattern 可以使用通配符。
通配符:
- *:表示 0 - 多个字符,例如: keys * 查询所有的 key。
- ?:表示单个字符,例如: wo?d , 匹配 word , wood
2. 判断 key 是否存在 exists
语法: exists key [key…]
作用:判断 key 是否存在
返回值:整数,存在 key 返回 1,其他返回 0。使用多个 key,返回存在的 key 的数量。
3. 设置 key 的生存时间 expire
语法: expire key seconds
作用:设置 key 的生存时间, 超过时间, key 自动删除。单位是秒。
返回值:设置成功返回数字 1,其他情况是 0 。
4. 查看key的剩余生存时间 ttl
语法: ttl key
作用:以秒为单位,返回 key 的剩余生存时间(ttl: time to live)
返回值:
- -1 :没有设置 key 的生存时间, key 永不过期。
- -2: key 不存在
- 数字: key 的剩余时间,秒为单位
5. 查看 key 所存储值的数据类型 type
语法: type key
作用:查看 key 所存储值的数据类型
返回值:字符串表示的数据类型
- none (key 不存在)
- string (字符串)
- hash (哈希表)
- list (列表)
- set (集合)
- zset (有序集)
6. 删除存在的key del
语法: del key [key…]
作用:删除存在的 key,不存在的 key 忽略。
返回值:数字,删除的 key 的数量。
五、字符串类型
字符串类型(string)是 Redis 中最基本的数据类型,它能存储任何形式的字符串,包括二进制数据,序列化后的数据, JSON 格式数据。
1. 基本命令 (set/get/incr/decr/append)
命令 | 说明 | 返回值 |
---|---|---|
set key value | 将字符串值 value 设置到 key 中 向已经存在的 key 设置新的 value,会覆盖原来的值 |
OK |
get key | 获取 key 中设置的字符串值 | 返回value值 |
incr key | 将 key 中储存的数字值加 1(只能对数字类型的数据操作) 如果 key 不存在,则 key 的值先被初始化为 0 再执行incr 操作 |
返回修改后的值 |
decr key | 将 key 中储存的数字值减1,其它与incr相同 | 返回修改后的值 |
append key value | 如果 key 存在,则将 value 追加到 key 原来旧值的末尾 如果 key 不存在,则将 key 设置值为 value |
追加字符串之后的总长度 |
2. key 所储存的字符串值的长度 strlen
语法: strlen key
说明: 返回 key 所储存的字符串值的长度
返回值:
- 如果key存在,返回字符串值的长度
- key不存在,返回
3. 截取字符串 getrange
语法: getrange key start end
作用: 获取 key 中字符串值从 start 开始到 end 结束的子字符串,包括 start 和 end,负数表示从字符串的末尾开始, -1 表示最后一个字符,超出字符串范围的截取, 获取合理的子串
返回值: 截取的子字符串。
使用的字符串 key: school, value: bjpowernode
4. 替换 setrange
语法: setrange key offset value
说明: 用 value 覆盖(替换) key 的存储的值,key中的值从 offset 开始的value长度的字符串被替换,不存在的 key 当做空白字符串。
返回值: 修改后的字符串的长度
5. 批量设置 mset
语法: mset key value [key value…]
说明: 同时设置一个或多个 key-value 对
返回值: OK
6. 批量取值 mget
语法: mget key [key …]
作用: 获取所有(一个或多个)给定 key 的值
返回值: 包含所有 key 的列表,不存在返回nil
六、哈希类型 hash
redis hash 是一个 string 类型的 field 和 value 的映射表, hash 特别适合用于存储对象。
1. 设定值 hset
语法: hset hash表的key field value
作用: 将哈希表 key 中的域 field 的值设为 value, 如果 key 不存在, 则新建 hash 表,执行赋值,如果有 field,则覆盖值。
返回值:
- 如果 field 是 hash 表中新 field,且设置值成功,返回 1
- 如果 field 已经存在,新值覆盖旧值,返回 0
2. 获取值 hget
语法: hget key field
作用: 获取哈希表 key 中给定域 field 的值
返回值: field 域的值,如果 key 不存在或者 field 不存在返回 nil
3. 批量设置域 hmset
语法: hmset key field value [field value…]
说明: 同时将多个 field-value (域-值)设置到哈希表 key 中,此命令会覆盖已经存在的 field,hash 表 key 不存在,创建空的 hash 表,执行 hmset.
返回值:设置成功返回 ok,如果失败返回一个错误
4. 批量获取域 hmget
语法: hmget key field [field…]
作用:获取哈希表 key 中一个或多个给定域的值
返回值:返回和 field 顺序对应的值,如果 field 不存在,返回 nil
5. 获取所有域和值 hgetall
语法: hgetall key
作用: 获取哈希表 key 中所有的域和值
返回值:以列表形式返回 hash 中域和域的值, key 不存在,返回空 hash
6. 删除一个或多个域 hdel
语法: hdel key field [field…]
作用: 删除哈希表 key 中的一个或多个指定域 field,不存在 field 直接忽略
返回值:成功删除的 field 的数量
7. 查看所有的域的field hkeys
语法: hkeys key
作用:查看哈希表 key 中的所有 field 域
返回值:包含所有 field 的列表, key 不存在返回空列表
8. 查看所有域的值 hvals
语法: hvals key
作用: 返回哈希表中所有域的值
返回值:包含哈希表所有域值的列表, key 不存在返回空列表
9. 查看给定域 field 是否存在 hexists
语法: hexists key field
作用: 查看哈希表 key 中,给定域 field 是否存在
返回值:如果 field 存在,返回 1,其他返回 0
七、列表 list
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部(左边)或者尾部(右边)
1. 插入多个值 lpush
语法: lpush key value [value…]
作用: 将一个或多个值 value 插入到列表 key 的表头(最左边),从左边开始加入值, 从左到右的顺序依次插入到表头
返回值: 数字, 新列表的长度
2. 获取多个值 rpush
语法: rpush key value [value…]
作用: 将一个或多个值 value 插入到列表 key 的表尾(最右边), 各个 value 值按从左到右的顺序依次插入到表尾
返回值:数字,新列表的长度
3. 获取区间内的值 lrange
语法: lrange key start stop
作用: 获取列表 key 中指定区间内的元素, 0 表示列表的第一个元素,以 1 表示列表的第二个元素; start , stop 是列表的下标值,也可以负数的下标, -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。 start , stop 超出列表的范围不会出现错误。
返回值: 指定区间的列表
4. 获取指定下标的元素 lindex
语法: lindex key index
作用: 获取列表 key 中下标为指定 index 的元素, 列表元素不删除, 只是查询。 0 表示列表的第一个元素,以 1 表示列表的第二个元素; start , stop 是列表的下标值,也可以负数的下标, -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
返回值:指定下标的元素; index 不在列表范围,返回 nil
5. 获取列表的长度 llen
语法: llen key
作用: 获取列表 key 的长度
返回值: 数值,列表的长度; key 不存在返回 0
6. 删除元素 lrem
语法: lrem key count value
作用: 根据参数 count 的值,移除列表中与参数 value 相等的元素, count >0 , 从列表的左侧向右开始移除; count < 0 从列表的尾部开始移除; count = 0 移除表中所有与 value 相等的值。
返回值: 数值,移除的元素个数
7. 根据下标修改值 lset
语法: lset key index value
作用: 将列表 key 下标为 index 的元素的值设置为 value。
返回值:设置成功返回 ok;key 不存在或者 index 超出范围返回错误信息
8. 插入 linsert
语法: linsert key BEFORE|AFTER pivot value
作用: 将值 value 插入到列表 key 当中位于值 pivot 之前或之后的位置。 key 不存在, pivot不在列表中,不执行任何操作。
返回值: 命令执行成功,返回新列表的长度。没有找到 pivot 返回 -1, key 不存在返回 0。
八、集合类型 set
redis 的 Set 是 string 类型的无序集合,集合成员是唯一的,即集合中不能出现重复的数据
1. 增 sadd
语法: sadd key member [member…]
作用: 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略, 不会再加入。
返回值:加入到集合的新元素的个数。不包括被忽略的元素。
2. 查 smembers
语法: smembers key
作用: 获取集合 key 中的所有成员元素,不存在的 key 视为空集合
3. 判断是否存在 sismember
语法: sismember key member
作用: 判断 member 元素是否是集合 key 的成员
返回值: member 是集合成员返回 1,其他返回 0 。
4. 获取个数 scard
语法: scard key
作用: 获取集合里面的元素个数
返回值:数字, key 的元素个数。其他情况返回 0 。
5. 删除 srem
语法: srem key member [member…]
作用: 删除集合 key 中的一个或多个 member 元素,不存在的元素被忽略。
返回值:数字,成功删除的元素个数, 不包括被忽略的元素。
6. 随机返回一个元素 srandmember
语法: srandmember key [count]
作用:只提供 key,随机返回集合中一个元素,元素不删除,依然在集合中;提供了 count 时, count 正数, 返回包含 count 个数元素集合,集合元素各不相同。 count 是负数,返回一个 count 绝对值的长度的集合,集合中元素可能会重复多次。
返回值:一个元素;多个元素的集合
7. 随机删除一个元素 spop
语法: spop key [count]
作用: 随机从集合中删除一个元素, count 是删除的元素个数。
返回值:被删除的元素, key 不存在或空集合返回 nil
九、有序集合类型 zset (sorted set)
redis 有序集合zset和集合set一样也是string类型元素的集合,且不允许重复的成员。不同的是 zset 的每个元素都会关联一个分数(分数可以重复), redis 通过分数来为集合中的成员进行从小到大的排序。
1. 添加 zadd
语法: zadd key score member [score member…]
作用: 将一个或多个 member 元素及其 score 值加入到有序集合 key 中,如果 member存在集合中,则更新值; score 可以是整数或浮点数
返回值: 数字, 新添加的元素个数
2. 区间查询,升序 zrange
语法: zrange key start stop [WITHSCORES]
作用:查询有序集合,指定区间的内的元素。 集合成员按 score 值从小到大来排序。 start, stop 都是从 0 开始。 0 是第一个元素, 1 是第二个元素,依次类推。 以 -1 表示最后一个成员, -2 表示倒数第二个成员。 WITHSCORES 选项让 score 和 value 一同返回。
返回值:自定区间的成员集合
3. 区间查询,降序 zrevrange
语法: zrevrange key start stop [WITHSCORES]
作用: 返回有序集 key 中,指定区间内的成员。其中成员的位置按 score 值递减(从大到小)来排列。 其它同 zrange 命令。
返回值:自定区间的成员集合
4. 删除 zrem
语法: zrem key member [member…]
作用: 删除有序集合 key 中的一个或多个成员,不存在的成员被忽略
返回值:被成功删除的成员数量,不包括被忽略的成员。
5. 获取成员个数 zcard
语法: zcard key
作用: 获取有序集 key 的元素成员的个数
返回值: key 存在返回集合元素的个数, key 不存在,返回 0
6. 根据分数范围获取元素(升序) 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
返回值: 指定区间的集合数据
7. 根据分数范围获取元素(降序) zrevrangebyscore
语法: zrevrangebyscore key max min [WITHSCORES ] [LIMIT offset count]
作用: 返回有序集 key 中, score 值介于 max 和 min 之间(默认包括等于 max 或 min )的所有的成员。有序集成员按 score 值递减(从大到小)的次序排列。 其他同 zrangebyscore
8. 根据分数范围获取元素数量 zcount
语法: zcount key min max
作用: 返回有序集 key 中, score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量
十、事务
事务是指一系列操作步骤,这一系列的操作步骤,要么完全地执行,要么完全地不执行。Redis 中的事务(transaction)是一组命令的集合,至少是两个或两个以上的命令, redis事务保证这些命令被执行时中间不会被任何其他操作打断。
1. 开启事务 multi
语法: multi
作用: 标记一个事务的开始。事务内的多条命令会按照先后顺序被放进一个队列当中。
返回值: 总是返回 ok
2. 执行 exec
语法: exec
作用: 执行所有事务块内的命令
返回值: 事务内的所有执行语句内容,事务被打断, 返回 nil
3. 放弃 discard
语法: discard
作用: 取消事务,放弃执行事务块内的所有命令
返回值:总是返回 ok
4. watch
语法: watch key [key …]
作用: 在开启事务之前,监视一个(或多个) key ,如果在事务执行(exec)之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
返回值: 总是返回 ok
WATCH 机制: 使用 WATCH 监视一个或多个 key , 跟踪 key 的 value 修改情况,如果有 key的 value 值在事务 EXEC 执行之前被修改了,整个事务被取消。 EXEC 返回提示信息, 表示事务已经失败
5. unwatch
语法: unwatch
作用:取消 WATCH 命令对所有 key 的监视。如果在执行 WATCH 命令之后, EXEC 命令或 DISCARD 命令先被执行了的话,那么就不需要再执行 UNWATCH 了
返回值:总是返回 ok
6. 事务中出错
- 事务执行 exec 之前, 入队命令错误(语法错误;严重错误导致服务器不能正常工作( 例如内存不足)),放弃事务。
- 事务执行 exec 命令后,命令执行错误,在 exec 执行后的所产生的错误,即使事务中有某个/某些命令在执行时产生了错误,事务中的其他命令仍然会继续执行。
十一、持久化
1. RDB
Redis Database(RDB),就是在指定的时间间隔内将内存中的数据集快照写入磁盘,数据恢复时将快照文件直接再读到内存。
RDB 保存了在某个时间点的数据集(全部数据)。存储在一个二进制文件中,只有一个文件。默认是 dump.rdb。 RDB 技术非常适合做备份,可以保存最近一个小时,一天,一个月的全部数据。保存数据是在单独的进程中写文件,不影响 Redis 的正常使用。 RDB 恢复数据时比其他 AOF 速度快。
(1)配置redis.conf
- 配置执行 RDB 生成快照文件的时间策略。
对 Redis 进行设置,让它在“ N 秒内数据集至少有 M 个 key 改动”这一条件被满足时,自动保存一次数据集。
配置格式: save <seconds> <changes>
save 900 1
save 300 10
save 60 10000 - dbfilename:设置 RDB 的文件名,默认文件名为 dump.rdb
- dir:指定 RDB 文件的存储位置,默认是 ./ 当前目录
(2)注意点
dump.rdb文件中存放的是二进制文件。
(3)总结
优点:由于存储的是数据快照文件,恢复数据很方便,也比较快
缺点:
- 会丢失最后一次快照以后更改的数据。 如果你的应用能容忍一定数据的丢失,那么使用 rdb 是不错的选择; 如果你不能容忍一定数据的丢失,使用 rdb 就不是一个很好的选择。
- 由于需要经常操作磁盘, RDB 会分出一个子进程。如果你的 redis 数据库很大的话,子进程占用比较多的时间,并且可能会影响 Redis 暂停服务一段时间(millisecond 级别),如果你的数据库超级大并且你的服务器 CPU 比较弱,有可能是会达到一秒。
2. AOF
Append-only File(AOF), Redis 每次接收到一条改变数据的命令时,它将把该命令写到一个 AOF 文件中(只记录写操作,读操作不记录),当 Redis 重启时,它通过执行 AOF 文件中所有的命令来恢复数据。
(1)配置redis.conf
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 文件,去掉无用的操作命令。缩小 aop 文件。
(2)注意点
- AOF文件中存放的命令的字符,可以打开看。
(3)总结
- append-only 文件是另一个可以提供完全数据保障的方案;
- AOF 文件会在操作过程中变得越来越大。比如,如果你做一百次加法计算,最后你只会在数据库里面得到最终的数值,但是在你的 AOF 里面会存在 100 次记录,其中 99 条记录对最终的结果是无用的;但 Redis 支持在不影响服务的前提下在后台重构 AOF 文件,让文件得以整理变小
- 可以同时使用这两种方式,redis默认优先加载 aof文件(aof数据最完整);
十二、主从复制
1. 主从配置(master/salve)
修改配置文件,启动时,服务器读取配置文件,并自动成为指定服务器的从服务器,从而构成主从复制的关系
编辑 Master 的配置文件:
- daemonize:yes 后台启动应用,相当于 ./redis-server & 的作用。
- pidfile:自定义的文件,表示当前程序的 pid,进程 id。示例:
pidfile /var/run/redis_6379.pid
- logfile:日志文件名
编辑 Slave 配置文件,除了配置与Master相同的那几项外,还要额外配置一项:
- slaveof :表示当前 Redis 是谁的从。当前是 127.0.0.0 端口 6379 这个 Master 的从。示例:
slaveof 127.0.0.1 6379
2. 手动实现主从复制
(1)查看信息
在客户端中执行:info replication
Master可以读数据和写数据,而Slave只能读数据
Master的信息:
Slave的信息:
(2)容灾处理
当master挂掉的时候,要提升某slave为master,并将其它slave挂载到新的master上
- 在一台Slave服务器上执行
slaveof no one
:将一台 slave 服务器提升为 Master (提升某 slave 为 master) - 在其它服务器上执行
slaveof master的ip master的端口
将 slave 挂至新的 master 上
(3)总结
- 不配置启动默认都是主
- 一个 master 可以有多个 slave
- slave 下线,读请求的处理性能下降
- master 下线,写请求无法执行
- 当 master 发生故障,需手动将其中一台 slave 使用 slaveof no one 命令提升为 master,其它 slave 执行 slaveof 命令指向这个新的 master,从新的 master 处同步数据
- 主从复制模式的故障转移需要手动操作,要实现自动化处理,这就需要 Sentinel 哨兵,实现故障自动转移。
3. 高可用 Sentinel 哨兵
Sentinel 哨兵是 redis 官方提供的高可用方案,可以用它来监控多个 Redis 服务实例的运行情况。Redis Sentinel 是一个运行在特殊模式下的 Redis 服务器。Redis Sentinel 是在多个Sentinel 进程环境下互相协作工作的。
Sentinel 系统有三个主要任务:
- 监控:Sentinel 不断的检查主服务和从服务器是否按照预期正常工作。
- 提醒:被监控的 Redis 出现问题时,Sentinel 会通知管理员或其他应用程序。
- 自动故障转移:监控的主 Redis 不能正常工作,Sentinel 会开始进行故障迁移操作。将一个从服务器升级新的主服务器。让其他从服务器挂到新的主服务器。同时向客户端提供新的主服务器地址。
(1)配置参数
sentinel.conf中主要的配置参数:
- port:设置Sentinel的端口号,系统默认 port 是 26379
- sentinel monitor <name> <masterIP> <masterPort> <Quorum 投票数>:修改监控的 master 地址
(2)启动哨兵
在Redis的src目录下,有一个redis-sentinel程序文件,通过redis-sentinel来启动哨兵,可以在一个redis中运行多个sentinel进程。
语法:./redis-sentinel sentinel配置文件
在 Master 执行 shutdown 后,稍微等一会 Sentinel 要进行投票计算,从可用的 Slave 选举新的 Master。查看 Sentinel 日志,三个 Sentinel 窗口的日志是一样的。
(3)监控
- Sentinel 会不断检查 Master 和 Slave 是否正常
- 如果 Sentinel 挂了,就无法监控,所以需要多个哨兵,组成 Sentinel 网络,一个健康的Sentinel
至少有 3 个
Sentinel 应用。彼此在独立的物理机器或虚拟机。 - 监控同一个 Master 的 Sentinel 会自动连接,组成一个分布式的 Sentinel 网络,互相通信并交换彼此关于被监控服务器的信息
- 当一个 Sentinel 认为被监控的服务器已经下线时,它会向网络中的其它 Sentinel 进行确认,判断该服务器是否真的已经下线
- 如果下线的服务器为主服务器,那么 Sentinel 网络将对下线主服务器进行自动故障转移,通过将下线主服务器的某个从服务器提升为新的主服务器,并让其从服务器转移到新的主服务器下,以此来让系统重新回到正常状态
- 下线的旧主服务器重新上线,Sentinel 会让它成为从,挂到新的主服务器下
(4)总结
主从复制,解决了读请求的分担,从节点下线,会使得读请求能力有所下降,Master 下线,写请求无法执行
Sentinel 会在 Master 下线后自动执行故障转移操作,提升一台 Slave 为 Master,并让其它Slave 成为新 Master 的 Slave
十三、其它设置
1. 设置密码
redis.conf中设置:
找到requirepass 所在的行,去掉注释,requirepass 空格后就是密码。
访问有密码的 Redis 两种方式:
- 在连接到客户端后,使用命令
auth 密码
,命令执行成功后,可以正常使用 Redis。 - 在连接客户端时使用
-a 密码
。例如 ./redis-cli -h ip -p port -a password
2. 导入别的配置文件
在配置文件中使用include
参数
include :包含原来的配置文件内容。
示例:include /usr/local/redis-4.0.13/redis.conf
十四、Jedis
1. 加入依赖
Maven仓库中查找Jedis:https://mvnrepository.com/
Jedis 对象并不是线程安全的,在多线程下使用同一个 Jedis 对象会出现并发问题。为了避免每次使用 Jedis 对象时都需要重新构建,Jedis 提供了 JedisPool。JedisPool 是基于Commons Pool 2 实现的一个线程安全的连接池,在Maven仓库中查找"commons pool"或者直接使用下面的依赖:
<!--Jedis依赖-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.3</version>
</dependency>
<!--Commons Pool 2依赖-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.6.0</version>
</dependency>
2. 创建连接池
public class RedisUtils {
//定义连接池对象
private static JedisPool pool = null;
//创建连接池
public static JedisPool open(String host, int port) {
if (pool == null) {
//创建连接池配置对象
JedisPoolConfig config = new JedisPoolConfig();
//最大Jedis实例数(默认值为8)
config.setMaxTotal(10);
//最大空闲连接数,设置这个可以保留足够的连接,快速获取连接
config.setMaxIdle(3);
//提前检查Jedis连接,取值true表示获取的Jedis连接一定是可用的
config.setTestOnBorrow(true);
//创建Jedis连接池,Redis没有访问密码时的使用方式
pool = new JedisPool(config, host, port);
//创建Jedis连接池,Redis有访问密码时的使用方式
//参数:Jedis配置对象,ip,端口号,连接超时时间,访问密码
//pool = new JedisPool(config,host,port,6*1000,"123456");
}
return pool;
}
//关闭连接池
public static void close() {
if (pool != null) {
pool.close();
}
}
}
3. 简单使用连接池
关键方法:
- 创建连接池:
JedisPool jp = RedisUtils.open("192.168.29.128", 6379);
- 从连接池中获取jedis对象:
Jedis jedis = jp.getResource();
- 对jedis操作是通过方法实现的,方法的名称与redis的命令一样。
- 不使用连接池,则直接new出一个Jedis对象
public static void main(String[] args) {
try {
//创建连接池
JedisPool jp = RedisUtils.open("192.168.29.128", 6379);
//从连接池中获取jedis对象
Jedis jedis = jp.getResource();
jedis.flushDB();
jedis.hset("hset1", "str1", "aaa");
String hget = jedis.hget("hset1", "str1");
Map<String,String> map = new HashMap<>();
map.put("id", "A0001");
map.put("name", "zs");
map.put("age", "23");
jedis.hmset("student", map);
List<String> list = jedis.hmget("student", "id", "name", "age");
System.out.println(list);
System.out.println(hget);
System.out.println(jedis);
} catch (Exception e) {
e.printStackTrace();
} finally {
RedisUtils.close();
}
}
4. 事务
事务使用的是Transaction
对象,然后使用该对象对redis数据库进行操作,提交之后返回List,里面存放着是否执行成功(OK/报错)
public static void main(String[] args) {
try {
JedisPool jp = RedisUtils.open("192.168.29.128", 6379);
Jedis jedis = jp.getResource();
jedis.flushDB();
Transaction tran = jedis.multi();
tran.set("str1", "aaa1");
tran.set("str2", "bbb2");
List<Object> lis = tran.exec();
for (Object li : lis) {
System.out.println(li);//OK, OK
}
} catch (Exception e) {
e.printStackTrace();
} finally {
RedisUtils.close();
}
}