目录
(12)批量设置一个或多个key-value,必须所有给定的key都不存在
(2)向指定key有序集合中加入一个或多个有score的value‘
(3)返回有序集合key中下标在指定范围内的元素(左闭,右闭)
(4)返回有序集合key中score值在指定范围内的元素(左闭,右闭)
(5)按从大到小的顺序返回有序集合key中score在指定范围的元素
(8)根据指定的score范围统计有序集合key中的元素个数
(2)给指定key集合的添加一个或多个field:value键值对
(3)返回指定key集合中的指定field字段的值(不删除)
(9)给指定key集合的添加一个field:value键值对,field不存在时新增成功
(2)设置Bitmaps中某个偏移量的值为0或1:setbit
(6)将多个Bitmaps做交、并、非、异或操作并保存到目标Bitmaps中
(4)将一个或多个HyperLogLog合并后的结果存储在新的HyperLogLog中
(5)获取以指定经纬度为中心和指定长度为半径的元素:georadius
一,Redis简介
Redis 是一种开源(BSD 许可)、内存中数据结构存储,用作数据库、缓存和消息代理。Redis 提供了诸如 string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型),等数据结构。Redis 内置了主从复制、Lua脚本、LRU、事务和不同级别的磁盘持久化,并通过哨兵模式实现高可用和集群实现自动分片。
BSD开源协议:
(original BSD license、FreeBSD license、Original BSD license)是一个给于使用者很大自由的协议,BSD 鼓励代码共享,但需要尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码,也允许使用或在BSD代码上开发商业软件发布和销售,因此是对商业集成很友好的协议。很多的公司企业在选用开源产品的时候都首选BSD协议,因为可以完全控制这些第三方的代码,在必要的时候可以修改或者二次开发。
GPL:
GNU通用公共许可证简称为GPL,是由自由软件基金会发行的用于计算机软件的协议证书,使用该证书的软件被称为自由软件。
这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。(每条单独的命令都是原子性的)
为了获得最佳性能,Redis 使用 内存数据集。根据您的用例,您可以通过定期将数据集转储到磁盘(RDB)或将每个命令附加到基于磁盘的日志来保存数据(AOF)。如果只需要一个功能丰富的网络内存缓存,也可以禁用持久性。
其他功能包括:
Redis 是用ANSI C编写的,推荐使用 Linux 进行部署。没有对 Windows 构建的官方支持(但微软自己做了支持)。
——摘自Redis官网
windons版redis下载地址https://github.com/microsoftarchive/redis/releases总之:
- K-V存储数据库,非关系型数据库
- 五大基本的类型:string,list,set,sorted set(zset),hash
- 三种特殊数据类型:bitmaps,hyperloglogs,geospatial
- 数据类型支持push/pop、add/remove、交并差集操作,且原子性
- 数据缓存在内存
- 周期性的持久化数据
- 支持主从同步
- 一般作为缓存数据库辅助持久化的数据库
- 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
非关系型数据库(NoSQL,Not Only SQL,不仅仅是SQL):
泛指非关系型的数据库,去掉了关系数据库的关系型特性(数据之间无关系,非常容易扩展),不依赖于业务逻辑方式存储,简单的k-v模式存储,不支持ACID
- 应用场景
- 对数据高并发读写
- 海量数据读写
- 对数据高可扩展性
- 分类
- 键值对存储数据:Redis
- 列存储数据库:Hbase(为处理数据量非常庞大的表,用于实时读写操作的场景)
- 文档型数据库:MongoDB
- 图形数据库:Neo4J
Redis中文网:
官网和中文网内容挺详细,可以多参照!!!
Redis文档中心 -- Redis中国用户组(CRUG)http://www.redis.cn/documentation.html
二,Redis安装
1,下载
2、安装编译
#解压
tar -zxvf redis-6.2.6.tar.gz
#进入目录
cd redis-6.2.6
#编译
make
#安装
make install
3,安装成功
可能遇到的问题:
①
可能是gcc版本的问题!执行如下命令,升级gcc的版本:
#升级到gcc到最新版本 yum -y install centos-release-scl yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils #注意:scl命令启用只是临时的,退出xshell或者重启服务器之后就会恢复到原来的gcc版本 scl enable devtoolset-9 bash #如果要长期生效的话,执行如下: echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile
4、安装目录简介
默认安装在/usr/local/bin目录下
5、默认配置启动
#进入目录
cd /usr/local/bin
#启动
./redis-server
6,客户端连接
./redis-cli
7,测试验证
8,关闭服务器
9,设置后台启动
三,基本操作
1,查看当前库所有key
- keys *
- keys * 1
2,判断某个key是否存在
- exists key名
3,查看指定的key的类型
- type key名
4,删除指定的key的数据
- del 要删除的key名
5,设置指定key的过期时间
- expire key名 过期时间
6,查看指定key的剩余过期时间
- ttl key名
返回值:
- >0的值:表示剩余过期时间
- -1:表示永远不过期
- -2:表示已过期
7,切换数据库
- select 数据库id(0-15)
Redis默认有16个数据库,从下标0开始-15,初始默认使用0号库;统一密码管理,所有库密码相同
8,查看当前数据库的key的数量
- dbsize
9,清空当前库
- flushdb
10,清空全部库
- flushall
四、五大基本数据类型
1,字符串(String)
(1)简介
- 一个key对应一个value
- String类型时二进制安全的,所以Redis的String可以包含任何数据(jpg图片或序列化的对象)
- 一个字符串value最多可以512M
(2)添加键值对
- set 键名 键值 [EX 超时秒数 | PX 超时毫秒数 | EXAT 时间戳 | PXAT 毫秒时间戳] [NX | XX]
NX:当数据库key不存在时,可以将key-value添加数据库
XX:当数据库key存在时,可以将key-value添加数据库
EX:key的超时秒数
PX:key的超时毫秒数
EXAT:key的超时时间戳
PXAT: key的超时毫秒时间戳
(3)查询对应键值
- get 待查询的key名
(4)追加字符串
- append 待追加字符串的key名 待追加的字符串
将给定的待追加的字符串追加到key名对应的值的末尾
(5)获得值的长度
- strlen key名
(6)在key不存在时设置key的值
- setnx key名 value值
(7)将key中存储的数字值增1
- incr key名
只能对数值型操作;如果操作不存在的key,新增值为1
(8) 将key中存储的数值减1
只能对数值型操作;如果操作不存在的key,新增值为-1
(9)将key中存储的值增减指定的值
- incrby key名 指定值
- decrby key名 指定值
(10)批量设置一个或多个key-value
- mset key1名 value1值 key2名 value2值 ......
(11)批量获得一个或多个value
- mget key1名 key2名 ......
(12)批量设置一个或多个key-value,必须所有给定的key都不存在
- msetnx key1名 key2名 ......
(13)获得值的范围
- getrange key名 起始位置 结束位置
类似于java的substring功能,前闭后闭
(14)替换所存储的字符串值
- setrange key名 起始位置 替换的值
(15)设置键值同时设置过期时间
- setex key名 [过期时间] value值
(16)设置新值同时返回旧值
- getset key名 新值
(17)数据结构
String的数据结构是简单动态字符串(SDS),是可以修改的字符串,采用预分配冗余空间的方式来减少内存的频繁分配。
内部为当前字符串实际分配的空间capacity一般要高于实际字符串长度len;
当字符串长度小于1M时,采用加倍方式扩容;
当字符串长度超过1M时,扩容时一次只会扩容1M;
字符串最大长度为512M。
2,列表(List)
(1)简介
- 一个键对应多个值
- 简单的字符串列表,按照插入顺序排序
- 可以在列表左边或右边添加元素
- 底层是双向链表,故:操作两端的元素是性能很高,索引下标操作中间节点时性能较差
(2)从两端(左边和右边)插入一个或多个值
- lpush key名 value1 value2 ......
- rpush key名 value1 value2 ......
(3)从两端(左边和右边)取出一个或多个值
- lpop key名 [count]
- rpop key名 [count]
(4)从列表1右边取出一个值,并插入到列表2左边
- rpoplpush key1名 key2名
(5)显示列表中指定范围内的元素
- lrange key名 起始位置 结束位置
- 0:表示左边第一个, -1:表示右边第一个
- 0 -1:表示获取所有
- 从左到右获取
(6)查看指定下标的元素
- lindex key名 下标
(7)获得列表长度
- llen key名
(8)在指定值前/后面插入新值
- linsert key名 before|after 指定的值 新值
(9)从左边删除指定个数的value
- lrem key名 指定个数 指定值
(10)将指定下标的值替换成指定值
- lset key名 指定下标 新值
(11)数据结构
List的数据结构是快速链表(QuickList);
在列表元素较少时,会使用一块连续的内存存储,是压缩列表,即ziplist结构;
在元素增加到一定数量时,将多个ziplist通过双向指针使用QuickList;
Redis将链表和压缩列表结合起来组成快速链表,即是使用双向指针将多个压缩列表连接起来
即满足增删该查性能,又控制了太多的空间浪费。
3,集合(Set)
(1)简介
- 与list类似,但set是可以自动排重的,同时可以判断某个元素是否在set集合内。
- String类型的无序集合
- 底层是一个value为null的hash表,所以新增、删除、查看的时间复杂度都为O(1)
(2)向指定key集合中加入一个或多个元素
- sadd key名 value1 value2 ......
(3)显示集合中所有的元素
- smembers key名
(4)判断某个元素在集合key中
- sismember key名
(5)返回集合key的元素个数
- scard key名
(6)删除集合key中的指定元素
- srem key名 元素1 元素2......
(7)随机从集合key中取出一个或多个元素
- spop key名 [count]
(8)随机显示集合key中的一个或多个元素
- srandmember key名 [count]
(9)把集合1中的指定元素移动到集合2
- smove key1名 key2名 指定元素value
(10)计算两个集合的交集
- sinter key1名 key2名
+
(11)计算两个集合的并集
- sunion key1名 key2名
(12)计算两个集合的差集
- sdiff key1名 key2名
(13)数据结构
Set数据结构是dict字典,且字段是哈希表实现的;
内部使用hash结构,所有的value指向同一个内部值;
Java中HashSet的内部实现是使用的HashMap,所有的value也都指向同一个对象。
4,有序集合(zset)
(1)简介
- 与set类似
- zset中每个成员都有一个评分(score),通过score使元素(member)从最低分到最高分排列集合
- 可通过score或排序获取指定该范围的元素
(2)向指定key有序集合中加入一个或多个有score的value‘
- zadd key名 score1值 member1值 score2值 member2值 ......
XX:仅更新已存在的元素,不添加新元素
NX:仅添加新元素,不更新现有的元素
LT:仅当新分数小于当前分数时才更新现有元素;不会阻止添加新元素
GT:仅当新分数大于当前分数时才更新现有元素;不会阻止添加新元素
CH:返回新增和修改的元素member个数,与过去具有相同分数的元素不会计算在内(zadd默认返回添加新元素的数量)
INCR:为指定元素的score加上指定值
(3)返回有序集合key中下标在指定范围内的元素(左闭,右闭)
- zrange key名 起始位置 结束位置 [REV] [withscores]
- REV: 按照逆序返回查询结果
- withscores:返回的结果带分数
(4)返回有序集合key中score值在指定范围内的元素(左闭,右闭)
- zrangebyscores key名 最小范围 最大范围 [wihscores]
(5)按从大到小的顺序返回有序集合key中score在指定范围的元素
- zrevrangebyscore key 最大范围 最小范围 [wihscores]
(6)给指定元素的score加上增量
- zincrby key名 增量值 元素
(7)删除有序集合key中指定的值的元素
- zrem key名 指定的元素
(8)根据指定的score范围统计有序集合key中的元素个数
- zcount key名 最小值 最大值
(9)返回指定值在有序集合的排序
- zrank key名 指定元素
(10)数据结构
zset底层两种数据结构:
hash:关联元素member和得分score,保证元素member的唯一性,可以通过元素member找到对应的score
跳表:给元素member排序,可以根据每个元素的score的范围获取元素
跳表的原理非常简单,跳表其实就是一种可以进行二分查找的有序链表。跳表的数据结构模型如图1:
可以看到,跳表在原有的有序链表上面增加了多级索引,通过索引来实现快速查找。首先在最高级索引上查找最后一个小于当前查找元素的位置,然后再跳到次高级索引继续查找,直到跳到最底层为止,这时候以及十分接近要查找的元素的位置了(如果查找元素存在的话)。由于根据索引可以一次跳过多个元素,所以跳查找的查找速度也就变快了
——摘自百度百科 ;
5,哈希(Hash)
(1)简介
- 一个键值对集合
- 是一个String类型的field和value的映射表
- 适合存储对象
- 通过 key名+field标签名 操作对应value值
- 大致格式如下:
(2)给指定key集合的添加一个或多个field:value键值对
- hset key名 field1名 value1值 field2名 value2值......
(3)返回指定key集合中的指定field字段的值(不删除)
- hget key名 field字段
(4)给指定key集合批量设置field:value键值对
- hmset key名 field1名 value1值 field2名 value2值 ......
(5)判断key集合中field字段是否存在
- hexists key名 field名
(6)列出key集合中所有field字段
- hkeys key名
(7)列出key集合中所有value值
- hvals key名
(8)给key集合中field字段加减指定值
- hincrby key名 field字段
(9)给指定key集合的添加一个field:value键值对,field不存在时新增成功
- hsetnx key名 field字段 value值
(10) 数据结构
Hash类型使用压缩列表(ziplist)和哈希表(hashtable)两种数据结构;
当field-value长度较短且个数较少时,使用ziplist;到一定数量时使用hashtable。
五,三种特殊数据类型
1,Bitmaps
(1)简介
- 采用计算机的二进制位作为存储信息的基本单位
- 类似于以位为单位的数组,数组中的每个单元都只能存储0和1
- 该数组的下标在Bitmaps中叫做偏移量,从0开始
- 底层存储是字符串,但提供了操作字符串的位的方法
位图不是实际的数据类型,而是在 String 类型上定义的一组面向位的操作。由于字符串是二进制安全 blob,其最大长度为 512 MB,因此它们适合设置为最多 2 的32次方不同的位;
位操作分为两组:常量时间单比特操作,如将位设置为 1 或 0,或获取其值;对位组的操作,例如计算给定位范围内的设置位数;
位图的最大优点之一是,它们在存储信息时通常会节省大量空间。例如,在由增量用户 ID 表示不同用户的系统中,仅使用 512 MB 内存即可记住 40 亿用户的单个位信息;
(2)设置Bitmaps中某个偏移量的值为0或1:setbit
- setbit key名 偏移量 0|1
如果寻址位超出当前字符串长度,则该命令会自动放大字符串。
(3)获取Bitmaps中某个偏移量的值:getbit
- getbit key名 偏移量
超出范围的位(寻址在存储到目标key中的字符串长度之外的位)始终被视为零。
(4)统计Bitmaps中1的个数
- bitcount key名 [start end]
start:代表起始字节数
end:代表结束字节数
计算的是字节位置
(5)查找具有指定值 0 或 1 的第一位:bitpos
- bitpos key名 0|1 [start end]
start:代表起始字节数
end:代表结束字节数
计算的是字节位置
(6)将多个Bitmaps做交、并、非、异或操作并保存到目标Bitmaps中
- bitop 指定操作 目标Bitmaps key1 key2 ......
提供的操作是 AND、OR、XOR 和 NOT
2,HyperLogLog
(1)简介
- 用来做基数统计的算法
- 在输入元素的数量或体积非常庞大时,计算基数所需要的空间是固定的、并且很小
- 每个HyperLogLog键只需要花费12KB内存,就可以计算接近2的64次方个不同元素的基数
- 只根据输入元素计算基数,不会存储输入元素本身
基数问题:求集合中不重复元素的个数问题
基数集:集合中包含全部不重复的元素的集合,比如{1,2,3,3,4,4,5}的基数集为{1,2,3,4,5}
基数:不重复的元素个数
基数估计:在误差可接受的范围内,快速计算基数
HyperLogLog是一种概率数据结构,用于计算唯一事物(从技术上讲,这指的是估计集合的基数)。
一组算法以内存换取精度:以标准误差的估计度量值结束,在 Redis 实现的情况下,该值小于 1%。此算法的神奇之处在于,不再需要使用与计数的项目数成比例的内存量,而是可以使用恒定的内存量!
(2)向指定key名的HyperLogLog中添加指定元素
- pfadd key名 元素1 元素2 ....
(3)计算指定的一个或多个key的近似基数
- pfcount key名1 key名2 ......
(4)将一个或多个HyperLogLog合并后的结果存储在新的HyperLogLog中
- pfmerge 新key名 key1 key2......
(5)序列化和反序列化
Redis 中的 HLL 虽然在技术上是不同的数据结构,但被编码为 Redis 字符串,因此您可以调用GET来序列化 HLL,并调用SET将其反序列化回服务器。
(6)底层存储
走近源码:神奇的HyperLogLog - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/58519480
3,Geospatial
(1)简介
将指定的地理空间项(经度、纬度、名称)添加到指定的键。数据作为排序集存储在键中;
- 该命令采用标准格式 x,y 的参数,因此必须在纬度之前指定经度。
可编入索引的坐标有限制:非常靠近极点的区域不可编入索引。EPSG:900913 / EPSG:3785 / OSGEO:41001 指定的确切限制如下:
- 有效经度为 -180 到 180 度。
- 有效纬度是从 -85.05112878 到 85.05112878 度。
当用户尝试索引指定范围之外的坐标时,该命令将报告错误。
注意:没有GEODEL命令,因为您可以使用ZREM删除元素。地理索引结构只是一个排序集。
(2)添加或更新地理位置:geoadd
- geoadd key名 经度 纬度 member1名 经度 纬度 member2名 ......
- XX : 只更新已经存在的元素。永远不要添加元素。
- NX:不要更新已经存在的元素。始终添加新元素。
- CH:修改返回值,从新增元素的数量,到变化的元素总数(CH是changed的缩写)。更改的元素是添加的新元素和已更新坐标的现有元素。因此,命令行中指定的具有与过去相同分数的元素不计算在内。注意:通常情况下,geoadd的返回值只计算新增元素的数量。
注意:XX和NX选项是互斥的。
(3)获取指定地区的坐标值:geopos
- geopos key名 member1名 member2名......
(4)获取两个位置之间的直线距离:geolist
- geodist key名 member1名 member2名 [m|km|ft|mi]
(5)获取以指定经纬度为中心和指定长度为半径的元素:georadius
- georadius key名 经度值 纬度值 半径长 m|km|ft|mi [withscore] [withdist] [withhash]
*****省略1000字和30张图(莫名其妙的丢失)
七,Redis订阅发布
*****省略5000字和100张图(莫名其妙的丢失)
八,事务
*****省略6000字和200张图(莫名其妙的丢失)
(100)Redis事务的特性
- 事务中的所有命令都会序列化、按顺序的执行;事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
- 队列中的命令没有提交之前都不会实际被执行,因为事务提交前任何命令实际都没有执行。
- 不保证原子性;事务中如果有一条命令执行失败,其后的命令仍然会被执行,而不是回滚。
如果建立事务时,某个命令报错(一般是语法错误、非法操作),执行时整个的所有队列都不会执行;
如果执行阶段,某个命令报错,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚。
九,Redis持久化
1,Redis提供的持久化方案
Redis 提供了一系列不同的持久性选项:
- RDB(Redis数据库):按指定的时间间隔执行数据集的时间点快照。
- AOF(仅追加文件):记录服务器接收的每个写入操作,这些操作将在服务器启动时再次执行,从而重建原始数据集。使用与 Redis 协议本身相同的格式以仅追加的方式记录命令。
- 无持久性:如果希望数据仅存在于服务器运行中,可以完全禁用持久化。
- RDB + AOF:可以在同一实例中同时组合 AOF 和 RDB。请注意,在这种情况下,当 Redis 重新启动时,AOF 文件将用于重建原始数据集,因为它保证是最完整的。
2,RDB
(1)介绍
在指定的时间间隔内将内存中的数据集快照写入磁盘,恢复时将快照文件直接读入内存中。
(2)RDB持久化过程
- Redis父进程创建(fork)一个子进程;(子进程负责进行持久化,父进程不会执行磁盘 I/O 或类似操作)
- 子进程先将数据写入到一个临时文件中,当持久化过程结束再将这个临时文件替换上次持久化好的文件;
- 当服务器宕机时,最后一次持久化好的数据在磁盘中,而最后一次持久化后的数据会丢失;
- 恢复时Redis将快照文件直接读入内存中。
整个过程中主进程不进行任何IO操作,确保了极高的性能;
适合大规模数据的恢复,且对于数据恢复的完整性不是非常敏感。
fork:
复制一个与当前进程一样的进程,新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,并作为原进程的子进程。
Linux中“写时复制技术”:一般情况父进程和子进程会共用同一段物理内存,只有进程空间的各段的内容发生变化时,才会将父进程的内容复制一份给子进程。
(3)持久化好的文件
默认保存Redis启动时命令行所在的目录下:
在配置文件redis.conf中,配置文件名和存储位置:
(4) 设置rdb保存策略
在配置文件redis.conf中,配置快照:
save:只负责保存,全部阻塞,手动保存;
bgsave:Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求;
lastsave:获取最后一次成功执行快照的时间;
flushall:会产生dump.rdb文件,但里面是空的,无意义;
开启压缩:消耗CPU资源;
关闭压缩:占用更大的存储空间
自从RDB的版本,,CRC64校验和被放在文件的末尾。
这使得格式更抗损坏,但在保存和加载RDB文件时有一个性能损失(约10%),所以可以禁用它以获得最大的性能;
RDB文件在checksum被禁用的情况下,checksum为0会告诉加载代码跳过检查。
(5)RDB 的优势
- RDB 是 Redis 数据的非常紧凑的单文件时间点表示形式。
- RDB文件非常适合备份。例如,您可能希望在最近 24 小时内每小时存档一次 RDB 文件,并希望每天保存一个 RDB 快照,持续 30 天。这使您可以在发生灾难时轻松还原数据集的不同版本。
- RDB非常适合灾难恢复,它是一个紧凑的文件,可以传输到远数据中心或Amazon S3(可加密)。
- RDB最大限度地提高了Redis的性能;只需要Redis父进程启动一个子进程,子进程负责进行备份,父进程永远不会执行磁盘 I/O 或类似操作。
- 与AOF相比,RDB在使用大型数据集启动时会更快。
- 在副本上,RDB 支持在重新启动和故障转移后进行部分重新同步。
(6)RDB的缺点
- Redis节点宕机时会丢失最新数据;通常会设置每五分钟或更长时间创建一个RDB快照;
- RDB 需要经常fork()子进程,以便使用子进程在磁盘上持久保存;
- 如果数据集很大,则 fork()可能会非常耗时;
- 如果数据集非常大且 CPU 性能不是很高,则可能导致 Redis 停止为客户端提供服务数毫秒甚至一秒钟。
2,AOF
(1)简介
每次 Redis 收到更改数据集的命令(例如set)时,它都会将其附加到 AOF。当重新启动 Redis 时,它将重新执行 AOF 以重建状态。
- 以日志的形式记录每个写操作(增量保存)
- 不记录读操作
- 只追加文件但不可以改写文件
- redis启动时读取文件重新构建数据,即将写指令从前到后执行一次
(2)AOF持久化过程
- 客户端请求写命令会append追加到AOF缓存区中;
- AOF缓存区根据AOF持久化策略将操作sync同步到磁盘的AOF文件;
- AOF文件大小超过重写策略或手动重写时,会对AOF文件重写,压缩AOF文件容量;
- Redis服务重启时,会重新load加载AOF文件中的写操作进行数据恢复。
(3)AOF持久化配置
在配置文件redis.conf中,配置AOF:
(4)AOF同步频率设置
在配置文件redis.conf中,配置AOF同步模式:
三种模式:
appendfsync no:redis不进行主动同步(fsync),由操作系统进行同步操作,速度很快;
appendfsync always:Redis每次写入操作都会立刻fsync日志,性能差但数据完整性高;
appendfsync everysec:默认,每秒fsync一次,如果服务宕机,会丢失一秒的数据。
(5)错误修复
(6)AOF缺点
- 占用更多的磁盘空间
- 恢复备份的速度更慢
十,Redis主从复制
1,简介
主从复制,是指将一台Redis服务器的更新数据根据配置和策略,自动复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。
默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
2,作用
- 数据冗余:主从复制实现了数据的热备份
- 故障恢复:当主节点出现问题时,可以切换到从节点提供服务,实现快速的故障恢复
- 读写分离:可以由主节点提供写服务,由从节点提供读服务
- 负载均衡:读写分离,分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以提高Redis服务器的并发量
3,配置主从
①启动三台Redis服务器
三台主机不用做任何配置,采用默认配置即可;
IP端口号分别是:
192.168.72.129:6379
192.168.72.130:6379
192.168.72.131:6379
②查看三台主机的运行情况
#打印主机的相关主从复制的信息
info replication
此时,三台主机都是maser角色,并且没有从机
③配置主从
slaveof ip 端口号
——配置某个实例成为指定ip和端口号的实力的从服务器
分别在192.168.72.130:6379和192.168.72.131:6379主机上执行:slaveof 192.168.72.129 6379.
④查看主机可从机的主从信息
此时可以看出主机并不显示从机的信息,同时从机显示主机不在线
说明从机并没有连接上主机,可通过一下两种方式解决:
第一种:redis.conf 下修改以下两个地方
1,关闭保护模式:protected-mode no 改成no
2. 注释ip访问限制 bind 127.0.0.1
第二种:redis.conf 下修改以下两个地方
1,开启保护模式:protected-mode yes
2. 添加ip访问限制 bind 127.0.0.1 (本机访问,如果需要其他的ip,自行加入 )
最后重启一下Redis就好了
⑤重新配置从机
⑥查看主从机主从复制信息
4,主从机读写测试
①从机已自动同步主机数据
②在主机写数据,从机读数据
③在从机写数据报错
5,从机宕机情况
重启从机后,主机变成master角色,需要重新通过slaveof命令配置从机;
配置完成后从机会同步主机的数据。
6,主机宕机情况
重启主机后,即可自动恢复,不需要做其他操作。
7,主从复制使用的三种机制
- 当主实例(主机)和副本实例(从机)连接良好时,主机通过向从机发送命令流保持从机副本数据更新,以复制任何对主数据集的更改操作;
- 当主机和从机之间断开时,由于网络问题或因为在主机或从机中检测超时,从机将重新连接并尝试进行部分重新同步(增量同步),从机将尝试仅获取部分在它断开期间错过的命令流;
- 当无返部分重新同步时,从机将要求完全重新同步(全量备份),主机将所有数据创建快照,发送到从机,然后随着数据集的变化继续发送命令流。
8,主从复制过程
- 从机启动并连接到主机后发送一个sync(同步)命令;
- 主机接收到命令后,启动后台的持久化进程,同时将所有加收到的修改数据集命令在后台进程中执行;
- 主机将整个数据文件发送到从机;
- 全量复制:从机在接收到数据文件后,将其存盘并加载到内存中;
- 增量复制:主机继续将新的所有修改数据集命令发送给从机进行同步;
9,级联从机
一个主机可以有多个从机,但过多的从机会在同步时消耗主机的性能;
副本能够接受来自其他副本的连接。将一台实例连接到从机上,形成从机的从机,通过从机备份数据。
此时:当主机宕机后,后面的从机可以通过slaveof no one命令被立刻升为主机,且后面的从机不用做任何修改。
slaveof no one #将从机变为主机
十一,哨兵模式
1,简介
Redis Sentinel 为Redis 提供高可用。能够在后台自动监控主机是否故障,如果主机发生故障将根据投票数自动将某一个从机转换为主机。完整功能列表如下:
- 监控。Sentinel 会不断检查您的主实例和副本实例是否按预期工作。
- 通知。Sentinel 可以通过 API 通知系统管理员或其他计算机程序,其中一个受监控的 Redis 实例出现问题。
- 自动故障转移。如果 master 没有按预期工作,Sentinel 可以启动一个故障转移过程,其中一个副本被提升为 master,其他额外的副本被重新配置为使用新的 master,并且使用 Redis 服务器的应用程序会被告知要使用的新地址连接时。
- 配置提供程序。Sentinel 充当客户端服务发现的权威来源:客户端连接到 Sentinel 以请求负责给定服务的当前 Redis 主节点的地址。如果发生故障转移,Sentinels 将报告新地址。
Redis Sentinel 是一个分布式系统:
Sentinel 本身旨在运行在多个 Sentinel 进程协同工作。多个 Sentinel 进程协作的优势如下:
Sentinel、Redis 实例(主实例和副本)以及连接到 Sentinel 和 Redis 的客户端的总和,也是一个具有特定属性的更大的分布式系统。
2,配置哨兵
①确定哨兵部署结构
在这里我有三台Redis服务器,分别在每台服务器上设置一个哨兵。
具体哨兵配置选型设计可以参照官网:
Redis Sentinel Documentation – Redis
https://redis.io/topics/sentinel
②修改配置文件sentinel.conf
配置说明:
sentinel monitor <master-group-name> <ip> <port> <quorum>
- mymaster:master组名,自定义;但不能包含特殊字符或空格,有效的字符集为A-z 0-9和“.-_”三类字符;
- ip port :要监视的主节点的ip和端口号;只需指定要监视的主节点,无需指定副本,因为Sentinel 会自动发现副本并将有关副本的其他信息自动更新配置;当副本提升为主副本时,配置文件将被重写;
- quorum:仲裁数量,即当2两个哨兵同意后,才可进行故障转移。
仲裁论点:
- 仲裁是需要就主服务器不可访问的事实达成一致的 Sentinel 数量,以便真正将主服务器标记为失败,并最终在可能的情况下启动故障转移过程。
- 仲裁仅用于检测故障。为了实际执行故障转移,需要将其中一个哨兵选为故障转移的领导者,并被授权继续进行。这只发生在大多数哨兵进程的投票中。
例如,有 3个 Sentinel 进程,并且给定主节点的仲裁设置为值 2,则会出现以下情况:
- 如果2个 Sentinel 同时同意主服务器无法访问,则2个哨兵中的一个将尝试启动故障转移。
- 如果总共至少有三个可访问的 Sentinels,则故障转移将获得授权并实际启动。
实际上,这意味着在故障期间,如果大多数 Sentinel 进程无法通信(即少数分区中没有故障转移),Sentinel 永远不会启动故障转移。
3,启动哨兵
#方式一
redis-sentinel /usr/local/redis-6.0.6/sentinel.conf
#方式二
redis-server /usr/local/redis-6.0.6/sentinel.conf --sentinel
- 在运行 Sentinel 时必须使用配置文件,因为系统将使用此文件来保存在重新启动时将重新加载的当前状态。如果没有提供配置文件或配置文件路径不可写,Sentinel 将直接拒绝启动。
- 默认情况下,Sentinels 会运行侦听TCP 端口 26379的连接,因此要使 Sentinels 正常工作,必须打开服务器的端口 26379 才能接收来自其他 Sentinel 实例的 IP 地址的连接。否则,哨兵无法交谈,也无法就该做什么达成一致,因此永远不会执行故障转移。
4,主机宕机
大概10秒左右可以看到哨兵窗口日志,切换了新的主机
5,原主机上线
哨兵窗口日志显示,129被自动加入成131的从机:
同时查看129主从信息,它变成了从机模式:
6,故障恢复流程
- 根据配置在所有从机中挑选一个从机,将其转成主机;
- 挑选出新的主机后,sentinel向其他从机发送slaveof命令,让其成为新主机的从机;
- 当原主机再次上线后,sentinel向其发送slaveof命令,使其成为新主机的从机。
挑选从机的条件依次:
- 优先级高的:redis.conf中配置,slave-priority 100,值越小优先级越高;
- 偏移量最大的:偏移量是指获得原主机数据的完整性;
- runid最小的:runid是redis实例启动后随意生成的标记此实例的id,依照此条件就相当于随机选取。
十二、集群
1,简介
Redis集群实现了对Redis的水平扩容,即启动N个redis节点,将整个数据库分布存储在这N个节点中,每个节点存储总数据的1/N。
Redis集群通过分区来提供一定程度的可用性:即使集群中有一部分节点失效或者无法进行通讯,集群也可以继续处理命令请求。
- Redis单机容量不够,水平扩容
- 流量均衡,将流量分不到集群中不同的服务器
- 客户端应用程序屏蔽ip地址端口号等信息
2,配置流程
(1)确定集群结构
选择6个节点,设计三主三从结构,三个主机作为三个分区保存全部数据,每个从机备份对应主机的数据。
在这里我的节点(保证对应的主从机不在同一物理机器上):
主节点 | 对应从节点 |
192.168.72.129:6379 | 192.168.72.130:6380 |
192.168.72.130:6379 | 192.168.72.131:6380 |
192.168.72.131:6379 | 192.168.72.129:6380 |
(2)删除所有节点的持久化数据
将所有节点的.rdb和.aof文件删除
(3)准备从机的配置文件
①复制从机的配置文件
②修改端口号
③修改持久化文件名
④修改.pid文件名
如果指定了pid文件,Redis会在启动时将其写入指定的位置,并在退出时将其删除。
当服务运行非守护进程时,如果配置中没有指定pid文件,则不会创建pid文件。当服务运行为守护进程时,即使没有指定pid文件也会使用,默认值为“/var/run/redis.pid”。
创建一个pid文件是最好的:如果Redis不能创建它,没有什么不好的事情发生,服务器将启动和正常运行。
注意,在现代Linux系统中/run/redis.pid“更符合标准,应该被使用。
⑤修改日志文件名
注意:
开启了AOP持久化方式的,还需要修改AOF文件的名称;
需要开启守护进程模式运行redis:daemonize yes
(4)修改主从机的集群配置
①开启集群模式
普通的Redis实例不能是Redis集群的一部分;只有作为集群节点启动的节点才能加入集群。
②开启并修改节点配置文件名
每个集群节点都有一个集群配置文件。此文件不能手动编辑。
它是由Redis节点创建和更新的。
每个Redis集群节点需要一个不同的集群配置文件。确保在同一系统中运行的实例没有重叠的集群配置文件名。
③ 开启节点超时时间
集群节点超时是指一个节点在失败状态下必须不可达的毫秒数。
超过该时间,集群就会自动进行主从切换。
(5)启动6个服务
查看进程情况:
查看日志:
每个节点都会为自己分配一个ID,此特定实例将永远使用此ID,以便该实例在集群环境中具有唯一的名称;ip地址和端口可能会更改,但节点ID在节点的整个生命周期内永远不会改变。
(6)查看node文件生成情况
(7)组合六个节点为一个集群
现在,已经运行了6个实例,我们需要通过向节点编写一些的配置来创建集群;
redis-cli:
可用于创建新集群、检查现有集群或重新分片等;
进入redis-6.2.6/src中:
./redis-cli --cluster create 192.168.72.129:6379 192.168.72.130:6379 192.168.72.131:6379 192.168.72.130:6380 192.168.72.131:6380 192.168.72.129:6380 --cluster-replicas 1
create:创建集群命令;
--cluster-replicas 1:为每个主节点创建一个副本;
最终,创建一个包含3个主节点和3个副本的集群。
一个集群至少要有三个主节点!
[OK] All 16384 slots covered
三台主机共提供16384个可用插槽提供服务。
3,客户端连接集群
-c 采用集群策略连接,否则在读写数据时重定向主机会出错:
自动重定向原理:
在客户端每次读、写键值时,redis会先计算该key所在的插槽,如果计算所得的插槽不在该客户端正在连接的服务器,redis会自动重定向到指定服务器。
4,查看集群信息
cluster nodes
slots(插槽):
- 一个Redis集群包含16364个插槽,每个key都属于这16384个插槽中的一个;
- 每个节点管理一部分插槽,如上图:master1包含0-5460,master2包含5641-19922;
- 通过CRC16(key)%16364计算每个key的插槽位置
5,批量操作的问题
批量读写时:
因为计算得key值可能不在同一个插槽内,所以无法切换,导致无法插入;
所以:
用组的概念 ,通过{}定义组,使redis通过{}中的内容判断要放的插槽;
6,查询集群指定插槽的信息
①查询指定个数的指定插槽的键
- cluster getkeysinslot 插槽号 key个数
返回5个名叫7629插槽中的键。
②查询指定键所在的插槽
- cluster keyslot 键名
③查询指定插槽中的键值对个数
- cluster countkeysinslot 插槽号
7,集群故障恢复
①主节点宕机
从机变成新主机
②原主机恢复
该原主机变成新主机的从机
③某一段插槽的主从节点都宕机
默认集群中该插槽段的数据全不能使用,同时无法存储,但其他段可用。
当该有一节点恢复时:
自动恢复
配置文件redis.conf中:
cluster-require-full-coverage yes: 当某一段插槽的主从机都宕机,整个集群都不可用;
cluster-require-full-coverage no:当某一段插槽的主动技都宕机,只有该插槽数据不可用,不可存储。
8,其他操作
新增、移除、迁移节点、重新分片等操作可以参考官网:
9,集群优缺点
- 扩容:集群10台运行内存为1T的服务器可以存放近10T的数据,若用一台服务器存放等量的数据需要10T的运行内存;
- 负载均衡,增大负载:每台主机处理一部分的请求,从机可以分摊读请求;
- 无中心化集群配置:配置方便,维护简单
十三,Jedis
Jedis是提供的java操作redis的API,通过在Springboot集成Redis使用。
十四,缓存雪崩、缓存击穿、缓存穿透、分布式锁
十五,集群压力测试
Redis中文网测试的方法:
REDIS benchmarks -- Redis中文资料站 -- Redis中国用户组(CRUG)http://www.redis.cn/topics/benchmarks.htmlRedis自带redis-benchmark的工具来模拟N个客户端同时发出M个请求。实验进行了如下对比测试:
配置:
3台虚拟机:1CPU+1G运行内存;50个客户端执行100000次请求(默认);
压测报告: