粉丝244获赞2390

今天和大家聊一个面试高频题啊,在分布式系统中,你怎么保证 m q 消息的顺序性?比如一个订单需要先创建再支付,最后发货,如果消息乱序了怎么办?他考察的其实是我们对于消息队列底层机制的理解深度和实战能力,我把它分为三个层面来解决啊。 第一个层面是 m q 本身的顺序保证机制,我们依赖的是消息队列的分区有序特性,比如用 rocket m q 或者卡不卡。核心原理其实很简单,同一个业务的消息必须发送到同一个队列的分区里。具体怎么做呢?我们在发消息的时候,拿订单 id 作为 message 或者帕丁纳 kia, 通过哈基算法,保证同一个订单的所有操作都打到同一个对联。这样一来,单个对联的内部天然就是 f i f o, 先进先出的消费者按顺序消费就不会乱了,这是保证顺序消息的基础。第二个层面 是消费端的串行化处理。你可能会问,对联里面有需就完事了吗?不是的,即使消息在对联里面排的好好的,消费端也有可能因为两种情况导致乱序啊。 情况一啊,提前 a c k 导致的乱序。情况二,易不处理导致的乱序。这个时候就该加锁机制上场了。方案一啊,加锁串形化。对于核心业务啊,我们给同一个订单的 id 加分布式锁或者本地锁, 确保同一个时刻只有一个县城在处理这个订单的消息啊,后面的消息必须等前一个处理完才能执行啊。方案二,版本号机制啊,对于非常严格的顺序业务啊, 我们可以用版本号,每个消息都带个递增的版本号,消费端根据版本号判断要不要处理啊,过期的消息直接丢弃了就行。第三个层面是异常场景的兜底方案,如果消费过程中出现了异常,比如 消费失败需要重试,我们绝对不能简单的把消息扔到队列的尾部,因为这样就乱序了。我们的做法是这样的,可重试的失败,把消息攥存到本地或者 read, 继续组织当前的队列的消费,等重试成功了再往下走,这样就不会影响顺序啊。 如果业务异常无法继续,则把这条消息投到此行队列,同时记录日期,然后跳过继续处理后面的消息,避免整个队列被一条坏消息卡死。 最后总结一下,这不是一个简简单单的配置就能搞定的问题啊。我们通过消息队列的分区机制,保证单队列有序,再通过消费端的串形化保证执行有序,最后通过异常兜底机制,保证系统不会因为个别消息 整体卡死,这才是我们在生产环境中保证 m q 顺序消息的一整套完整方案。 yolo 加瓦更新不停,我们直播间见!

大家好,今天我们来学习 java 中的 list。 list 是 集合框架中的一个接口,代表有序的元素集合。简单说,它就像一个有顺序的盒子, 我们可以按锁银访问元素,比如第一个,第二个。要记住,这是 java 处理集合数据的基础哦。要创建一个 list, 我 们通常用实线类,如 arraylist, 或者 list, 等于 new arraylist 的 s, 比如这样就能创建一个存储字串的列表。大家注意,范型歹离指定元素类型,确保类型安全。添加元素时用 add 方法,比如 list add 叉哇,就把叉哇加到末尾。 add 意思还可以指定位置,如 list add 零 first 插入到开头,要记住,如果缩引超出范围会报错, 别犯这个错误哦。获取元素很简单,用 get 方法传入缩隐,缩隐从零开始,例如 string first 等于 list get 零获取第一个元素。大家要注意缩隐不能超过 size 负一, 否则会抛出 index auto of bound section。 异常删除元素用 removes 有 两种方式, remove 用的 index 删除指定所引的元素或 remove object 误删除匹配对象,比如 list removes 零删除第一个元素, 记住删除后元素会迁移,所以会变哦。便利, list 是 常用操作,可以用 for 循环 for int 等于零 i list size size i 加加猜测,或者用 for reach for string s list strike 更高效的是迭代起 iterate, 避免病发修改问题。 想知道列表有多少元素,用 size 方法,比如 int count 等于 list sizes, 返回当前元素数量, 这是个 o e, 操作非常快。大家要记住在循环中用它来避免重复计算。 arraylist 是 基于动态数据库实现的,所以 geti 随机访问很快,是常数时间,但插入或删除元素时可能需要移动数据,效率较低。 比如在中间插入元素时, arraylist 不 如 linklist 快。 linklist 是 基于双向链表的,插入和删除元素很快,因为只需调整指针。但 getty 随机访问慢,需要从链表头便利,比如频繁增删场景,用 linklist 更合适哦。 最后要注意, arduino list 和 link 的 list 都不是县城安全的,如果在多县城中使用,需加锁同步或改用 copy on rt arduino list, 比如多个县城同时修改列表,会导致数据不一致,大家要避免这个坑。

大家好,今天我们来学习 java 中的 arraylist。 首先要记住 arraylist 是 一个动态数据库,实现了 list 的 接口,可以存储各种对象,而且大小能自动调整。比如它比普通数据库灵活多了,适合存储不确定数量的元素。 接下来我们看如何声明和初识化。 alexis 语法是 alexis 类型特列里斯等于 l alexis, 比如 l alexis t string names 等于 l alexis。 这样就创建了一个字母串列表。大家要注意案情,制定了存储类型,避免类型错误。添加元素很简单,用 a d 方法,比如 list dd。 java 就 把元素加到末尾了。 a, d, d 还支持在指定位置插入,如 list a d d first, 插入到开头,要记住这是动态添加,列表会自动扩容。访问元素时用 get index 方法缩隐,从零开始,比如 list get 零,返回第一个元素,大家要注意缩隐范围,如果越界会抛出 index auto off bounds exception。 异常 编程时要小心。删除元素有两种方式, remove int index。 删除指定位置的元素,如 list removes 零或者 remove object o。 删除第一个匹配的元素,如 list removes。 java 删除后,列表会自动调整大小。检查列表大小,用 size 方法返回元素个数 s m t, 检查是否为空。比如 if list s m t s m t 才可以判断列表是否没元素, 这在处理用户输入或数据时很实用便利。 alexed 可以 用 for 循环 for in i 等于零 i list size size 加加 for 或者增强 for 循环 for string i list 兹德还可以用 iterate 迭代器。 便利时要注意不要修改列表结构,否则可能出错。 a realist 和普通数组的区别,数组大小固定声明时指定 a realist 大 小可变,自动扩容,比如 int r r 等于 new int 十大小不能变, a realist 能随意添加元素, 大家要理解这个核心优势。县城安全方面, our list 不是 县城安全的,如果多县城同时修改,可能导致数据不一致。要记住,在病发环境下,可以用 collections sincronized list 的 包装或改用 copyright list。 性能注意点, aureolelist 在 末尾添加元素很快, o 一 但在中间或开头添加删除较慢。 o 一 因为需要移动元素,比如频繁在开头操作时考虑用 linkedlist, 大家要合理选择集合类。

拿 reddit list 当对联, lpush rpop 那 是幼儿园玩法,想靠谱点得用 brpop 主色等消息,省得 cpu 空转。 同时 aof 直接话必须打开,不然重启会丢失。还有个土办法,消费完先别删,用个备用 list 存着,等业务真处理成功了再删。这类用中间键解决时间场景的题。我整理了很多企业级项目的真实用法,粉丝寻找,老范领取, 但它终究是 reddit, 不是 专业队列,我们只拿它处理不重要的通知或睿智争到的订单秒杀。这种场面还是得上 rocket mq 或卡夫卡,不然消息堆积或数据问题够你头疼的。你们羡慕你 reddit list 还扛过哪些活?评论区说说。

欢迎大家来到每日一题的时间,今天我们来看一下这道题的正确答案。首先说这道题的答案选择的应该是 c 选项,就是以上这种面向对象的特征,我们应该称之为叫方法重载或者叫 overload, overload 啊, 那这里先强调一个 b 选项啊, b 选项这个覆盖,可能大家可能没太听过这个覆盖呢,严格医生来说它应该指的叫方法重写,所以也有人就这么叫叫覆盖。 方法重写覆盖是一个意思啊,大家听到这个词比较陌生,那为什么说覆盖呢?大家想想这个重写,重写就是我子类继承了父类,然后把父类的方法呢,觉得不好的,我把它重新写了一份,那么这样的话,你以后再调用,不管是多肽的效果还是正常写子类的效果, 调用的一定是重写之后这个方法,那原有的那个父类方法就被你盖住了,这种感觉啊,没有一个要隐藏的东西,所以这个隐藏呢不太对,当然 d 也不对,所以这道题选择的是 c 选项啊。那么沿着这道题呢,我们来深入的去探讨一下关于这道题的一些知识点,以及我们面向对象思想这种养成,好吧,嗯,首先来看这道题考察点就叫方法重载,我们先把这个重载的事给大家说说哈,这个我们叫做方法 重载,对吧啊,专有名词叫做 over load, 那 当然提到这的话,我们通常可能会提到一个叫做方法重写的概念,这个重写我们叫做 over load 啊,所以这两个你可以放在一块去类比着记,但是不要记混了啊。首先我跟大家之前说过,我们说这东西怎么记呢?你要先从这个结构上来记,对吧?大家想想,它叫方法重 载,这个叫方法重写,那肯定就是方法本身的事,对吧?那我们知道方法呢,它是类中的一个成员, 所以如果你想去记他的话,你得从方法本身来记,那么方法他是类中的一个成员,他不能单独的存在,对吧?你得需要把它放在一个类里边,那所以从这几个角度来出发去思考,第一件事就是我这个方法到底所属的类有几个 啊?你前面这个方法重载,大家知道他应该是一个类,那方法重写的话,肯定是产生了继承关系的两个类,对吧?他是个数就不太一样的啊。那么第二个呢,就是方法本身的问题,第二个就是方法本身的结构,但这个方法的结构呢?他有这么几个啊。首先第一个叫做权限修饰符,第二个叫做特征 就是符,对吧?第三个我们叫方法的返回值类型,第四个是方法的名字,那第五个是这样一个括号,它里面写的叫参数列表。然后第六个呢,它其实是叫抛出的异常,还有一个结构大括号引起来的,这个我们叫方法体, 对吧?所以你从方法的结构上去思考,方法重载这几个结构什么要求?那方法重写你对应着看方法重写他们几个又是什么要求,对吧?当然我们说这个方法,这结构咱们写了七个部分,这七个部分他又不都是必须有的,比如说修饰符,这个方法有也行,没有也可以,比如说抛出了异常,你没有也行,对 吧?比如说参数列表这个东西,咱们写小括号当然是必须存在的,小括号里面不见得写东西,那所以这些到底有还是没有?那如果有什么样的特点,那重载要求是什么? 对不对?随这些搞清楚啊。那么从咱们的题目来讲,这道题已经给你准备的很清晰了,这道题告诉你的是一个类中,对吧?首先一个类中的一堆方法,许多方法嘛,对吧?哎,所以方法重载就是概念,是一个类下的一堆方法,它们构成了什么重载呢?它们要求的是方法的参数、个数、 类型或顺序各不相同啊。一个或者两个参数,咱俩不一样。同样是一个参数,你是整数,咱俩不一样,对吧?同样是两个,你是整数,我是此数, 那我是 int 和 si, 你 是 si 和 int, 咱俩数学不一样,所以这些都叫做参数不同。那么同时传回的返回值呢?它是可能不相同的,就是你相同也可以, 不相同也可以,因为重载的概念,我们没有要求返回值的事,对吧?大家想想方法重载就是一个类下好几个方法名字一样,参数不同,那你在调方法的时候,第一个通过名字来确认它,那名字如果相同情况下,第二个你可以通过参数来确认它。 如果你名字和参数都相同,这个方法就钓不着了,因为咱俩长的一模一样,真假名号长的一模一样,你怎么去分分分开?如果你分不开的话,我这个方法没没等掉呢,他就执行不了,你就更别说返回结果的事。那返回结果是方法执行以后的效果,我 连执行都执行不了,怎么返回?所以他跟返回值没什么关系, ok 吧?所以这个是从概念上强调的知识点。但是如果这一块内容呢?大家有一些问题,你可以回头翻看咱们之前给大家讲的知识点,但是如果这一块内容呢?大家有一些问题, ok 了,那么这块我再多说一嘴。很多同学可能在这里面基本上就停留在方法重写 和承载的概念上,你从这两个层面上去分析概念,我觉得不用死记硬背,你去对照着比较就可以知道了。但是关键的问题是,我们其实更多的是要强调讲面向对象编程思想的设计上 啊,我们一直在强调说这个设计问题,不是说面向对象,他是个写法。很多同学可能在学校里面没有听过我的课啊,没有听过我的课,都听过别的老师的课,你会发现很多老师咱们讲的话都是这样的,讲面向对象,他就是个写法的。什么叫累 啊?什么叫类?类就 class 嘛,对吧。然后什么叫类中的成员,成员有好几个呢,对吧?属性啊,方法呀、构造方法呀,包括咱们写的代码块啊,对吧?这些。所以你认识这个写法其实不那么重要,因为大家书本上都这么讲,很多老师都这么写,没有什么区别的。那区别在于我们提到的设计上, 所以这个设计怎么体现呢?首先第一个,大家知道这个类呢?这个类我们是自定义,对吧?啊?自定义,因为很多时候比如写好的类,像 string 呢,什么 integer, math 呀,就这样的类,我们都称之为工具类,包括咱们用到的什么 aries 的 这种集合都是工具类,那么工具类都是别人写好的,那我们为什么要自定义类呢? 对吧?就是因为你可能需要了很多你的逻辑,然后你需要做什么事情,所以你首先想到的问题就是第一件事,你为什么要自定义?这个为什么很重要?为什么要 自己定义这个类就要先想清楚啊,老师,别人干,那别人干你就非得干嘛?你非得跟他一样吗?啊?不是这样的,对吧?一定是想为什么,那么第二个如果你想清楚了,为什么啊?当前这个类我的作用是干嘛的?那么接下来在想这个类中 为什么要有这些成员?因为他说类当中成员是有四个结构,但是四个不是必须非得写的,我这个类下可以没有属性,我这个类里边可以没有代码块, 我说累,甚至可以没有方法,但为什么非得有,对吧?你要想清楚为什么要有这个成员,而且这个成员是用来干嘛的?我们写的成员,尤其是第一重要的就是方法,因为他是做事的嘛,对吧?他是做事的。第二个重要的就是属性,因为属性他是用来存取东西的, 它就是个长长局的变量,叫全局变量,生命之间很长的一个变量,存东西的,所以方法在设计很重要。那么你想清楚了为什么之后第三件事,因为我们更多情况下是设计方法或者属性。第三件事你要想这个方法或者是属性的结构问题,尤其是方法, 对吧?咱们说了好多,那些什么修饰符呀,返回值为什么要有,对吧?你方法设计为什么有两个参数,不是一个参数等等等等这些,这些才叫设计,否则的话你这道题目选择对了,其实对于你未来的开发没有什么帮助。很多同学可能老师我知道方法重载这个概念,但你会发现你在设计的时候基本上没有用过这样的方法重载,那么就是个大问题了, 等等吧。啊,所以我希望大家可能从这道题目来讲,呃,除了概念以外,深入去理解关于他背后设计的思想问题。当然如果你有什么问题的话,也可以呃去扫码或者是通过给我留言的方式,然后咱们再做一些交流,深入的理解和交流。好吧,希望大家每天可以跟阿托老师跟着读一教育,一起成长一点点啊。那今天我们这堂课就到这吧。

今天我们来给大家讲一讲 java 的 一个数据结构,叫做 arraylist, 实际上在我们的内存空间里,它就是一个连续的空间,然后它被分割开啊,比如说这是一个格子,两个、三个、四个,那我这个呃是一个长度为四的一个数值, 那这个 arraylist 呢?它底层其实是用数值来实现的,它的特点就是我们可以随机的去查询这里面任何的一个值。比如说我这里存的是 a, 这是 c、 b、 d, 你 如果想查这个 b 啊,他其实就是在这数组里面第一、第二、第三个格子,他很快就是可以查到。但是呢这种数据结构他也有他的一个缺点。你比如说我想往这里面中间突然加这么一个值的话,那这个没有位置,那只能你先扩出了一个格子,然后把这个 d 往后挪一个位置,然后这个中间就出现了一个空格。比如说你加了一个 m, 那这样的话你就会需要把很多很多的这个元素啊都开始移动,或者你删除也是一样。比如这有一个你先把它删掉,删掉之后呢,这个后面的都要向前移动它,这样的话它会损耗很多的性能啊。 但是它查询起来的确是比较快,它属于一种集合的这种类型啊,你要存多个元素的时候,我们就要用到这种额外的这种数据结构了。

我们通过 java 来实现站,站有两种实现方式,顺序实现。底层是通过数组实现的,列式实现,底层是通过列表实现的。我们先来看顺序实现。在顺序实现中,我们会定义一个底层数组 date, 用于存储数据。 top 是 占顶指征,始终指向占顶元素。 例如,此时站中存储三个元素,零号所在位置是站底,二号所在位置是站顶,二号以上的位置还没有存储数据。我们来看一下站的成员变量和构造器。 max size 定义了底层数组的长度为一百, date 就是 我们的底层数组。 top 是 占顶元素的左眼,始终指向占顶元素。在构造方法中,我们创建了底层数组,并初次化。 top 默认值为负一,表示占为空,判断占是否为空。 如果 top 为负一,表示占为空,返回处,否则呢?返回 false, 获取占顶元素。调用 stack m t 方法判断占是否为空。如果占为空,返回 no, 否则返回占顶元素 入占,将元素 e 压入占中。如果 top 已经等于 max size 减一了,表示占已满,否则将 e 放入底层数组所引为 top 加一的位置 出站。如果站为空,返回 no, 否则呢?返回对应的占顶元素,并将 top 值减一。便利 通过 stack m t 方法判断站是否为空。如果站不为空,通过放循环输出底层数组中的所有元素,所以位置为零表示占底,所以位置为 top, 表示占顶。我们再来看一下链式实现,紧挨着头节点的节点是占顶, 列表的尾部就是占底节点类。 date 存储着当前节点的数据, next 指向下一个节点。 构造器通过六关键字在堆中创建头节点的存储空间,头节点的 next 指向 on, 表示此时站为空,判断站是否为空。如果头节点的 next 为 on, 表示站为空返回处,否则呢?返回 false 库,取占顶元素, 调用 stack m t 方法判断站是否为空。如果站为空,返回 non s 的 next 就是 站点元素。返回站点元素节点的 date 入站,通过 new 关键字在堆中创建节点 node, 设置 node 的 date 为 e, 通过投插法将 node 插入列表。 头插法我们讲列表的时候已经说过了,这里再复习一下创建 node, 将 node 的 next 指向 s 的 next, 再将 s 的 next 指向 node 出站,如果站为空,返回 no, 否则获取占顶元素,再将占顶节点从列表中删除,返回占顶元素。 我们来看一下移除节点的流程,让 top 指向 top 的 next, 最后技 c 会自动释放 top 所指向的节点空间,便利通过 stack mg 方法判断站是否为空。如果站不为空,通过外循环输出链表中的所有节点, 链表的首原节点是站顶,链表的尾节点是站底。好,今天就聊到这,如果你有任何问题,欢迎大家在评论区或粉丝群里讨论。

今天我们给大家介绍另一个在 java 里面经常使用到的一个数据结构,这叫 link 的 list, 它是通过一种链表来实现的,我们看一下这个链表它是长成什么样的,就像我们这个生活当中一个铁链子一样的,那这个 它属于一个节点,就是我们可以向里面存数据的一个地方,比如说有一个绳子也好,或者铁链也好,连到另一个节点上面, 然后这个这个节点又把它穿到另外一个节点,当然你从后面也可以向前面来走。这种链表的这种形式呢,最底下我们给他存的是数据,他比较适合,比如说我们想向中间添加一个元素,比如说这是一个 h, 想添到这个 a 和 c 之间, 我把这个给他剪断,把这个也给他剪断,把这个给他哎放到这,把他连到这来,同样这个让他指向这样,然后把这个再指到这里面来, 这样的话我们就很顺利的在这个 a 和 c 中间给他插入了一个这种节点啊。删除也是一样,如果你想,比如说我把这个给他删掉,那你就把它剪断,剪断之后把原来这个再恢复过去。 所以呢这种 link 的 list 他 这种添加和删除是非常方便的,但是他如果要查找的话,可能就比较麻烦。查询的时候呢,你必须从这个头部,然后一个一个的这样往后走,走走走,如果你要找到在 在中间或者靠后的位置,那你可能要找很多才能把它找到。这种修改比较频繁的场景,你可以考虑用这种叫 link 的 list。