本文目录
redis中如何保证原子性
什么是原子性?
说到原子性就不得不提事务操作,原子性操作指在一个事务中,多个步骤操作要么一起成功完成,要么一起失败,不能出现部分成功或部分失败,对于redis来说,事务队列中的命令要么全部执行,要么都不执行,所以redis的事务具有原子性。
Reids如何执行事务?
弄清楚redis如何保证原子性操作之前,我们先来了解下redis事务操作的流程。
一个事务从开始到结束会经历以下三个阶段:
- 事务开始
- 命令入列(先进先出)
- 事务执行
举个例子:
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基础,比如一些关键字,八大基本类型,变量的声明,类,方法,逻辑语句,逻辑操作符等等,这是写JAVA程序的基础,然后就是一些JAVA常用的API了, 例如集合元素(数据存储元素)Collection,List,Set,Map等等,又如文件IO操作的API,一般被分为字节流和字符流,大多数培训机构这样划分,实际上底层实现是分为Input/ Output, Writer/ Reader两种类型的接口,后者是对前者的包装(不懂的就用IED点进去看),最后就是一些规范或者框架了,比如JDBC创建数据库链接(这个阶段一般会要求学习数据库),主流企业级开发框架Spring,主流的ORM框架Hibernate和Mybatis等等!如上是大多数培训都会有的课程!如果想要追随主流,这些是远远不够的!
进阶学习则为多线程,高并发!首先是对多线程的理解,从最基本的线程状态,synchronize关键字开始理解线程这个概念,从CPU多核心层次来深化线程概念!其次是熟悉了解对多线程常用的控制类,ReentrantLock,ReentrantReadWriteLock,LockSupport,Condition等获取锁和释放锁以及面试经常被提及的AQS-Abstract QueuedSynchronizer框架,然后是对常用的原子类操作如AtomicInteger,LongAdder等,重要是要了解到自旋和CAS的实质以及容易出现的问题,最后是经常用的高并发API,如可以控制并发的CountDownLatch,Semphore等,高并发可控队列ArrayBlockingQueue,LinkedBlockngQueue等等还有高并发缓存ConcurrentHashMap,CopyOnWriteArrayList等等。
近些年,随着分布式,微服务的受热程度不断提高,不断出现了诸如Spring Cloud,Dubbo,包括阿里最近开源整个前两者生态的Nacos微服务框架!在分布式和微服务扮演者更多角色的中间件火热起来!例如分布式协调者Zookeeper,Chubby,Eureka等,消息中间件KAFKA,ActiveMQ,Rabbit MQ等,数据库中间件Mycat,Sharding-Sphare等,都是基于分布式业务系统诞生的中间件,还有一些非关系型数据库,Redis,MongoDB,Memchche等等。JAVA技术栈异常的庞大,可能程序员一直处在学习和应用过程中!
还不能少了一些承载应用的容器,比如Tomcat,Jetty,Undertown等等这些WEB容器都基于HTTP协议,因此你必须要了解HTTP协议,才能去优化容器!另外,还要了解到这类容器对应的高可用方案!Nginx既用作WEB容器又具有负载均衡的作用,通过对Nginx的负载均衡又可实现Nginx的高可用!负载均衡在高并发,分布式当中扮演者相当重要的角色,需要了解到四层负载与七层负载的区别!
当然了,开发怎么少的了运维操作。Doker,k8s等
这里可能要谈的东西还有很多,欢迎收藏,我会不定时去,希望可以帮到读者,也希望大家可以一起分享一下自己的观念看法!