queued(redis中如何保证原子性
发布时间: 2023-07-18

本文目录

redis中如何保证原子性

什么是原子性?

说到原子性就不得不提事务操作,原子性操作指在一个事务中,多个步骤操作要么一起成功完成,要么一起失败,不能出现部分成功或部分失败,对于redis来说,事务队列中的命令要么全部执行,要么都不执行,所以redis的事务具有原子性。

Reids如何执行事务?

弄清楚redis如何保证原子性操作之前,我们先来了解下redis事务操作的流程。

一个事务从开始到结束会经历以下三个阶段:

  1. 事务开始
  2. 命令入列(先进先出)
  3. 事务执行

举个例子:

redis 》 muti //开启一个事务(此命令会修改客户端状态属性,将其状态变为事务开启)

ok //并且立即执行后返回结果

reids 》 set name hunk

queued //此命令送入队列排队等候,不会立即执行

redis 》 get name

queued //送入队列排队...

redis 》 exec //从队列中取出命令全部执行,最后执行结果全部返回给客户端

ok //返回结果

这里需要注意的是,redis接受到一个命令后,服务器端判断该命令是立即执行还是放入队列,是根据客户端是否开启了事务状态来决定的,例如:

当一个客户端处于事务开启状态时,如果服务器接收到exec命令,服务端将遍历这个关联的事务队列,并执行当中的所有命令,最后全部返回给客户端:

如何保证事务原子性?

我们已经知道了redis事务是如何执行的:客户端通过muti命令开启事务状态,服务端通过事务队列存储客户端所有命令,然后客户端发起exec命令后,服务器执行队列的中所有的命令,最后取消客户端事务状态、清理队列、返回结果到客户端。

watch命令:wathc命令是一个乐观锁,通过锁我们可以实现原子性操作,wantch可以在exec执行之前监视任意数量的数据库键key,并在exec执行时,检查被监视的key是否已经被修改,如果是,服务器就会拒绝执行当前事务中所有命令,返回客户端执行失败的回复。比如以下两个客户端执行命令的过程,如下图:

T4时刻,客户端B修改了name键值,而客户端A已经监听了name键,T5时刻客户端A执行exec命令时,服务器发现name已经被修改,因此服务器会拒绝执行A的事务,每个redis数据库都有一个watch_keys的字典,通过该字典,redis服务器可以知道数据库中哪些键正在被监视,如下图:

比如,如果“name”被修改,那么客户端a,b的redis_dirty_cas标识被打开,当服务器收到客户端a或b发来的exec的命令时,服务器判断客户端是否打开了该标识来决定是否执行事务,如下图:

一致性保证:一致性是指数据符合预定义的要求,没有无效的或非法数据,这是保证原子操作的必然结果,redis事务中会出现不可预知的错误,如何保证数据一致性呢?我们从三个redis事务可能出错的地方来看看

  • 入队错误:如果事务在入队命令时,命令不存在或格式不正确,那么redis将拒绝执行这个事务。

redis 》 muti ok

redis 》 set name “aa“ queued

redis 》 liuneng (error) err unknown command ’liuneng’

redis 》 get name queued

redis 》 exec (error) execabort transaction discarded because of previous errors.

服务器未发现未知命令 liuneng 所有拒绝执行队列中命令,也就终止了此项事务,保证了原子性、数据一致性。

  • 执行错误:如果redis在执行队列中的命令过程中出现了错误,它会继续执行队列中剩下的命令,已执行的命令和结果不会被出错的命令所影响,因为出错的命令会被服务器识别出来并予以错误处理,不会对数据库做任何修改,也不会影响数据一致性。
  • 服务停器机:服务器停机后redis在重启时会根据持久化模式,选择对应的AOF或RDB文件来恢复数据,事务中途发生的停机不会影响数据库一致性。

java线程间如何通信

谢邀!

Object的wait方法、notify方法和notifyAll方法可以实现线程间的通讯,wait方法让当前线程等待,同时释放持有的锁,notify方法可以唤醒一个等待的线程,notifyAll方法可以唤醒所有等待的线程,线程间采用竞争的策略获取执行计划,但是需要注意的是这三个方法需要配合synchronized关键字使用。

希望对你有所帮助!

高中文化学习JAVA编程,想找个程序员的工作,该如何开始学习

高中可以尝试去学习JAVA,但首先要做到如下几点:(前方高能)

第一:态度认真,包括工作态度,学习态度,请教别人问题的态度。在自己努力学习,努力工作的过程中,会遇到很多人,这些人可能有些技术不怎样但不要排斥他们,因为他们熟悉的领域可能你不懂,有些呢技术特牛,但很重视别人的尊重,很重视别人的态度,而好的态度则可能换来他的帮助,有些也是玩忽职守,工作敷衍的人,千万远离这部分人,保持距离。

第二:思维严谨,编程语言重在逻辑思维,保持逻辑思维的清晰严谨性,有利于自己接触很多的知识和技能,这是精通JAVA的前提条件,很多报了培训机构的人都是断在缺乏严谨的思维能力迫使自己无法在这个行业生存下去。

第三:自我认知,认识自己的不足和短板,发挥自己的优势,这是每个职业人的必修课,但在编程语言这门学科上刚开始不是这样,刚开始你需要懂JAVA基础,你需要懂数据库,你需要知道如何运用一些主流框架完成开发,你需要学习各种中间件来加以应用!但是,最终也必然是这样,当你的技术面达到一定程度,必然要选择一个自己感兴趣的方向或者自己的强项去摸索去探究!

以上三点是作为优秀程序员的必修课,是接下来学习工作过程中要把持的习惯,坚持自己的目标,把握自己的心态,控制自己欲望!

紧接着你需要一个能够接纳你的培训机构为你指点迷津,充实自己的JAVA技术栈,学习如何面向企业完成开发任务!培训学习是一个比较痛苦的过程,你会接触到自己内心不曾预见的另外一个世界!刚开始对这个世界迷迷糊糊甚至培训过后也是迷迷糊糊,这时候你需要不断地唤醒自己,不要迷失自我,沉下心来学习,理解,记忆,实操!

作为初学者,学习,理解,记忆,实操,这四项是王牌,是自己知识结构体系扩充的王牌!边学习,边理解,边记忆,边实操!实际上,学历代表的就是这样四种学习能力,高中学历的你如果拥有这样的学习能力,JAVA自然也不在话下,但是只会HelloWorld是不行的,这连JAVA基础都算不上,这只是作为JAVA编程语言的展示!真正入行,得从计算机体系,计算机操作系统来了解,和学习,了解到什么层次?即CPU,存储(文件系统)和信息传输,任何语言,都是基于CPU,存储,信息传输的,了解这些再去理解编程语言就会事半功倍!

JAVA语言的学习过程大多是从了解Linux操作系统的文件系统基本命令开始的,这与JAVA多运行在Linux系统上分不开的,其次是面向对象编程的特点和JAVA的发展史,这里要重视的是面相对象编程,即OOP思想。然后是JAVA基础

微信