redis是如何持久化的?怎么用redis来处理分布式事务的?lua脚本怎么用?

  • 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),异步确保,最大努力 来保证消息正确传达
在消息正确传达的基础上,我们使用数据库锁来完成大事务中的部分事务,获取到锁(行锁/表锁)即可进行操作, 获取到锁的前提下,可以再次加锁即可重入锁

猜你喜欢

转载自blog.csdn.net/qq_38229608/article/details/87874789