什么是持久化?
利用永久性存储介质将数据进行保存,在特定的时间将保存的数据进行恢复的工作机制称为持久化。
为什么要持久化
防止数据的意外丢失,确保数据安全性
持久化过程保存什么
命令
save
Copy
作用
手动执行一次保存操作
RDB配置相关命令
RDB启动方式——save指令工作原理
注意:save指令的执行会阻塞当前Redis服务器,直到当前RDB过程完成为止,有可能会造成长时间阻塞,线上环境不建议使用。
命令
bgsave
作用
手动启动后台保存操作,但不是立即执行
RDB启动方式 —— bgsave指令工作原理
注意: bgsave命令是针对save阻塞问题做的优化。Redis内部所有涉及到RDB操作都采用bgsave的方式,save命令可以放弃使用,推荐使用bgsave
bgsave的保存操作可以通过redis的日志查看
docker logs myredis
配置
save second changes
作用
满足限定时间范围内key的变化数量达到指定数量即进行持久化
参数
配置位置
在conf文件中进行配置
RDB启动方式 ——save配置原理
注意:
AOF功能开启
配置
appendonly yes|no
配置
appendfsync always|everysec|no
AOF文件重写是将redis进程内的数据转化为写命令同步到新AOF文件的过程,简单说是将同一个数据的若干条命令执行结果转化为最终结果数据对应的指令进行记录。
1、手动重写,由客户端输入命令行,对AOF文件进行重写
bgrewriteaof
2、自动重写,在配置文件写相应的命令,在达到条件时自动对AOF进行重写
自动重写触发条件设置
//触发重写的最小大小
auto-aof-rewrite-min-size size
//触发重写须达到的最小百分比
auto-aof-rewrite-percentage percent
自动重写触发比对参数( 运行指令info Persistence获取具体信息 )
//当前.aof的文件大小
aof_current_size
//基础文件大小
aof_base_size
自动重写触发条件
工作原理
对于不同场景下的RDB和AOF的选择难题:
redis在执行指令过程中,多条连续执行的指令被干扰、打断、插队
会引发跟数据库类似的脏读,看到其他事务操作修改的内容,产生并发问题。
redis事务就是一个命令执行队列,将一系列预定义的命令包装成一个整体。当执行时,一次性按照添加顺序依次执行,中间不会被打断或者干扰。
开启事务
multi
取消事务
discard
执行事务
exec
需要注意:加入事务的命令暂时存进任务队列中,并没有立即执行,只有执行exec命令才开始执行
定义事务的过程中,命令格式输入错误怎么办?
定义事务的过程中,命令执行出现错误怎么办?
注意:已经执行完毕的命令对应的数据不会自动回滚,需要程序员自己在代码中实现回滚。
对售罄的货物追加补货,4个业务员都有权限进行补货。补货的操作可能是一系列操作,牵扯到多个连续操作,如何避免重复对一个商品进行补货呢?
对 key 添加监视锁,在执行exec前如果key发生了变化,终止事务执行
watch key1, key2....
取消对所有key的监视
unwatch
用于解决超卖问题,如何避免最后一件商品不被多人同时购买?
在用户买商品的过程中,如果采用watch的方式,大量请求到达时,会有很多请求的watch监视的库存键被修改,导致后面的减库存事务失效而不执行
watch只能检测到键的变化,而不能保证事务中的逻辑正确性;例如如果事务中的命令是根据库存数量来判断是否可以下单,那么即使watch指令没有发现库存键被修改,也有可能出现多个客户端同时读取同一个库存数量,导致超卖
虽然redis是单线程,但多个客户端对同一数据同时进行操作时,如何避免不被同时修改?
使用 setnx 设置一个公共锁
//上锁
setnx lock-key value
//释放锁
del lock-key
注意:上述解决方案是一种设计概念,依赖规范保障,具有风险性
依赖分布式锁机制,某个用户操作时对应的客户端宕机,且此时已经获取锁,如何解决?
分析:
由于锁操作由用户控制加锁解锁,必定存在加锁后未解锁的风险
需要解锁操作不仅依赖用户控制,系统级别要给出对应的保底方案
分布式锁加强
使用 expire 为锁key添加时间限定,到时不释放,放弃锁
expire lock-key seconds
pexpire lock-key milliseconds
由于操作通常都是微秒或毫秒级,因此该锁定时间不宜设置过大。具体时间需要业务测试后确认。
设置过有效期的数据,并到达了有效期,称为过期数据
过期的数据真的被删除吗?
根据删除策略来定
创建一个定时器,当key设置有过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作
优点:节约内存,到时删除,快速释放不必要的内存
缺点:CPU压力大,影响redis服务响应时间和指令吞吐量
总结:用处理器性能换存储空间
数据到达过期时间,并不做处理,直到下次访问该数据时再进行删除
优点:节约CPU性能,发现必须删除时候才能删除
缺点:内存压力很大,出现长期占用内存的数据
总结:用存储空间换处理器性能(以时间换空间)
并不针对于过期数据,而是当新数据进入redis,内存不足的情况。
策略内容:
相关配置:
建议采用检测易失数据
可以看作一个string类型的二进制字符串,多用于存储状态,毕竟二进制只能来表示两种状态。
比如记录5名同学的性别,男为1,女为0,前三号为男同学,后两名为女同学,则可得字符串为
11100,可如此记录。
基础操作
获取指定key对应偏移量上的bit值
getbit key offset
设置指定key对应偏移量上的bit值,value只能是1或0
setbit key offset value
扩展操作
业务场景:1、统计每天一部电影是否被点播
2、统计每天有多少部电影被点播
3、统计每周/月/年有多少部电影被点播
4、统计年度哪部电影没有被点播
对指定key按位进行交、并、非、异或操作,并将结果保存到destKey中,参数为op
bitop op destKey key1 [key2...]
bitcount 20880808 //统计有多少个1
bitop or 08-09 20880808 20880809 //将20880808的键值与20880809的键值做or操作,并将值存储于08-09键中
bitcount 08-09 //统计08-09键值有多少个1
统计指定key中1的数量
bitcount key [start end]
统计独立UV(不重复的数据的数量)
HyperLogLog是用来做基数统计的,运用了LogLog算法
什么是基数:基数是数据集去重后元素的个数
如数据集合{1,3,5,7,5,7,8},则基数集为{1,3,5,7,8},基数为5(即基数集的长度)
基本操作
添加数据
pfadd key element1, element2...
统计数据
pfcount key1 key2....
合并数据
pfmerge destkey sourcekey [sourcekey...]
1、用于基数统计,不是集合,不保存数据,只记录数量而不是具体数据
2、核心是基数估算算法,最终数值存在误差
3、误差范围:基数估计结果是一个带有0.81%标准错误的近似值
4、耗空间小,每个hyperloglogkey占用12k的内存用于标记计数
基本操作
添加坐标点
geoadd key longitude latitude member [longitude latitude member ...]
georadius key longitude latitude radius m|km|ft|mi [withcoord] [withdist] [withhash] [count count]
Copy
获取坐标点
geopos key member [member ...]
georadiusbymember key member radius m|km|ft|mi [withcoord] [withdist] [withhash] [count count]
Copy
计算坐标点距离
geodist key member1 member2 [unit]
geohash key member [member ...]
由于单机redis在现在的高并发项目条件下,存在许多风险与问题:
即当前提供服务的redis服务器为主,做主服务器备份的redis服务器为slave服务器,如果主服务器挂掉,那么启动slave服务器,因为slave服务器与主服务器的数据一致,可以保证服务的畅通性。
主从复制简单介绍:
1、读写分离:master写,slave读,提高服务器的读写负载能力
2、负载均衡:基于主从结构,配合读写分离,由slave分担master负载,并根据需求变化,改变slave的数量,通过多个节点分担数据读取负载,大大提高Redis服务器并发量和数据吞吐量。
3、故障恢复
4、数据冗余:实现数据的热备份
5、高可用基石:基于主从复制,构建哨兵模式与集群,实现Redis的高可用方案
建立连接的流程:
数据同步阶段:全量复制+部分复制
注意:在master进行bgsave操作的过程中,还是会有一些新数据的产生,这些数据放在复制缓冲区中,由6、7、8步来完成。因此需要的同步的数据包括全量复制和部分复制。
数据缓冲区:保存影响master变更的指令,和AOF一样
数据同步需要注意的地方:
对于master需要注意的地方
对于slave需要注意的地方
命令传播阶段
其中第7步得细说,匹配runid和offset,首先匹配runid是看是不是需要部分复制的那个slave,如果不是,直接进行全量复制;再看看offset是否匹配,可能存在缓存池溢出的情况,这个时候也要全量复制
slave掉线太多,或延迟过高,导致数据复制效率低;通过配置文件,可以指定条件来关闭同步功能
7.5 主从复制整体工作流图
哨兵是一个分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制选择新的master并将所有slave连接到新的master
监控:不断检查master和slave是否正常运行
master存活检测,master与slave运行情况检测
通知:当被监控的服务器出现问题时,向其他(哨兵间、客户端)发送通知
自动故障转移:断开master与slave连接,选取一个slave作为master,将其他slave连接到新的master,并告知客户端的新服务器地址
注意:哨兵也是一台redis服务器,只是不提供数据服务
通常哨兵的配置数量为单数(三个及以上,如果是偶数,它们投票容易打平)
用于同步各个节点的状态信息,包括:
1、获取各个sentinel的状态(是否在线)
2、获取master的状态(master属性:runid,role等 各个slave的信息)
3、获取slave的状态