敞开生长之旅!这是我参加「日新方案 12 月更文挑战」的第十九天,点击检查活动概况

大家好,我是Zhan,一名个人练习时长一年半的大二后台练习生

这篇文章是温习 Redis 缓存实践中的问题 的学习笔记

假如有不对的地方,欢迎各位纠正

与君同舟渡,达岸各自归


导言

我们知道MySQL的业务,知道Java中的业务,可是好像很少提到Redis中的业务,可是在Redis中我们也要确保指令依照次序串行化履行行列中的指令,那么Redis是如何在指令层次和底层完成业务的呢?

Redis 业务的本质是一次性、次序型、排他性的履行一个行列中的一系列指令。业务支撑一次履行多个指令,一个业务中一切指令都会被序列化。在业务履行过程,会依照次序串行化履行行列中的指令,其他客户端提交的指令请求不会刺进到业务履行指令序列中。

那么本文就从应用层面来讨论一下Redis 业务的运用:


Redis 根本指令

mysql中的业务开端是begin,完毕时commit,那么Redis怎么敞开业务和完毕业务,又有哪些不同于MySQL的地方呢?

  • MULTI:敞开业务,也便是从这个位置开端,一切的指令都会逐个放进行列中,也便是相当于MySQL的begin
  • EXEC:履行业务中的一切操作指令,也便是提交业务,相当于MySQL中的commit
  • DISCARD:撤销业务,也便是回滚业务,相当于MySQL中的rollback
  • WATCH:监督一个或多个key,假如业务在履行前,这个key被其他指令修正,就会中止业务,这便是区别于MySQL的地方
  • UNWATCH:撤销一切的watch监督

WATCH & CAS

既然有区别于MySQL的指令,那么它有什么运用场景呢?其实它和CAS有关,我们来看看详细怎么运用:

先给一个场景,由于我们的对策都来源于问题,那么有了问题,我们才会去规划对应的指令去处理,那么场景如下:

关于一个商品,它的存货只要一件了,可是现在两个线程都进来了,两个线程都判别存货大于0,都通过了校验,进行了下单操作,导致最终呈现了两个订单,且订单的余量变为了-1

Redis 攻略面经(七)-- Redis 事务的使用和特点

可是有了WATCH我们就很好处理这个问题了,我们先回顾一下watch的作用:监督一个或多个key,假如业务在履行前,这个key被其他指令修正,就会中止业务,根据这个作用我们能够写出下面这段代码:

WATCH capacity
capacity = GET capacity
capacity = capacity - 1
MULTI 
SET capacity &capacity
EXEC

有了上面的代码,假如在WATCH履行之后,EXEC履行之前,有其他的客户端修正了容量的值,当时客户端的业务就会失效,程序要做的便是不断的重试,直到没有发生碰撞停止

那WATCH完成的底层逻辑是什么呢?

其实便是我们所说的CAS:compare and swap

  • 在开端业务前监听一个键值对,记录下来这个值
  • 在提交业务后,拿到键值对的当时值
  • 进行两个值的比较(Compare):
    • 假如值没有发生改变,就履行业务
    • 假如值发生了改变就回滚业务
  • 最终撤销监控,流程图如下:

Redis 攻略面经(七)-- Redis 事务的使用和特点

业务的回滚

大家假如有运用联系型数据库的经验,或许知道Redis在业务失败的时候不进行回滚,而是持续履行余下的指令后觉得有点古怪

那或许大家有疑问:DISCARD不是回滚吗?但其实这里所谓的回滚是指:在EXEC履行过程中,呈现了指令的过错,会持续往下履行,不会因而中止,所以其实我们能够发现这些问题属于是开发者呈现的编程过错,而不是生产环境的问题,因而不需要对回滚进行支撑,由于回滚不能处理编程过错带来的问题,例如对过错的类型履行了INCR,很明显这不是回滚能处理的

业务的四大特性

原子性

首要通过上文知道,运行期的编程过错是不会回滚的,所以其实很多文章由此说Redis业务违背原子性的

可是Redis官方文档给出的解说是:一切的指令,要么悉数履行,要么悉数不履行,而不是悉数履行成功

共同性

redis业务能够确保指令失败的状况下得以回滚,数据能恢复到没有履行之前的样子,是确保共同性的,除非redis进程意外终结。

阻隔性

redis业务是严格遵守阻隔性的,原因是redis是单进程单线程形式,能够确保指令履行过程中不会被其他客户端指令打断。可是,Redis不像其它结构化数据库有阻隔等级这种规划。

持久性

redis业务是不确保持久性的,这是由于redis持久化战略中不管是RDB仍是AOF都是异步履行的,不确保持久性是出于对性能的考虑。


业务的其他完成办法

Redis 业务除了指令,有其他的完成办法嘛?

其实关于一个Java后台程序员,与我触摸最多的Redis业务其实是Lua脚本,很少运用到MULTI,DISCARD,EXEC这种指令。

基于Lua脚本,Redis能够确保脚本内的指令一次性、按次序的履行,当然,它也不提供业务运行过错的回滚,与上述的状况共同


总结

本文讲了Redis业务的指令行运用以及一些介绍:

  • 关于Redis指令:我们提到了根本的业务敞开、提交、弃用三种指令
  • 然后介绍了WATCH这个特别的指令,介绍了它的运用场景和运用原理
  • 关于业务的回滚:Redis的业务回滚机制相关于其他的很特别,我们也做了讲解
  • 关于业务的四大特性:我们分别讲述了四个特性的完成,而且提到并没有完成持久性
  • 关于业务的其他完成办法:这便是我们后台程序员或许触摸比较多的Lua脚本 信任读完今天的文章,大家能对Redis 业务的运用,以及Redis业务的特色有了更深一步的理解~

友链

  • Redis 攻略面经(一)– 常见数据类型
  • Redis 攻略面经(二)– 关于持久化,你了解多少?
  • Redis 攻略面经(三)– 详解内存收回的两种战略
  • Redis 攻略面经(四)– 详解主从复制中的同步数据
  • Redis 攻略面经(五)– 详解岗兵机制
  • Redis 攻略面经(六)– 缓存实践中的问题

✒写在最终

都看到这里啦~,给个点赞再走呗~,也欢迎各位大佬纠正以及补充,在评论区一同沟通,共同进步!也欢迎加微信一同沟通:Goldfish7710。我们明天见~

Redis 攻略面经(七)-- Redis 事务的使用和特点