- redis的持久化
save和bgsave的区别,bgsave是fork了一个子线程去实现持久化,在bgsave期间,客户端仍可以处理客户端请求
- redis的过期策略
可以设置过期时间,但是要考虑当同一时间出现很多过期的话,会造成正常业务卡顿,redis内部每过25秒即(贪心)读取设置了过期时间的list,如果过期占其中超过1/4则会继续执行去过期稀释过期list,实际使用中最好在过期时间上加随机数
从库中的过期不会自动执行,是一种懒加载,根据文件删除,或者在访问时判断
过期时间是对整个hash来说的而不是hash中的某个kv对
- lua脚本
redis作为远程字典服务,当把它看成是一个操作内存的数据库时它满足ACID原则,因为本身提供了锁(但是并不如db提供的锁功能完善,如超时等问题)
但是当我们使用lua操作时需要注意: - 原子性
redis依赖lua,单线程只要开始执行就会将当前script执行完 - 一致性
redis没有回滚一说,lua中先执行成功的语句不会因为后面执行的语句的失败而失败 - 隔离性
- 持久性
在执行成功后才会写入文件
理解:redis中的事务不能完全的满足ACID
思考?
既然redis是单线程的,为何lua执行卡死时可以执行其他命令终止执行线程?
因为存在钩子设计
但是当lua中有执行写操作,无法简单终止
-
redis实现分布式事务?
这里与其说"redis实现分布式事务"不如说redis作为中间件帮助完成柔性事务
为什么选择了redis?
是因为单线程操作吗?
个人理解:为了解决应用分布式带来的问题,用redis作为第三者见证人(分布式锁的关键一环)保证业务正常进行(事务的ACID特性得到满足相对于db层面的事务处理:例如修改某账户的余额,在service中查或者改在同一个事务中,是满足原子性的,但是如果是分布式部署的应用甚至db,就不能保证业务是正常可靠的了 而对redis作为db而言,可以使用lua脚本保证一定的原子性(可能会出现执行中,后半部分失败而前半部分已执行的情况);也可以使用锁来保证一定的原子性:例如修改余额的业务中,查时即开启锁,在修改完成后释放锁
-
分布式事务?
面临的主要问题:网络分区导致的消息不确定性
业务上的原子操作无法 在数据库层面简单的使用事务保证原子,不同的节点应用,操作不同的数据库两个维度都极易产生这种需求
例如:与tcp/ip协议的三次握手情形类似
上一个应用成功,下一个应用失败,如何保证上一个应用回滚操作
上一个应用成功,发生网络分区,下一个应用无法判断上一个的执行结果
上一个应用成功,下一个应用成功,发生网络分区,上一个应用无法判断下一个执行结果
参考mysql
柔性事务,cap中取a(高可用[应用集群,多个copy副本])p(部署在不同的物理机上[copy副本间的同步,不同节点间的消息传递])而强调最终一致性
DB层面常见的实现思路有:两阶段,补偿(TCC),异步确保,最大努力 来保证消息正确传达
在消息正确传达的基础上,我们使用数据库锁来完成大事务中的部分事务,获取到锁(行锁/表锁)即可进行操作, 获取到锁的前提下,可以再次加锁即可重入锁