如果重复消费了,可能是什么原因导致的
RocketMQ重复消费,指的是同一个消息重复来了多次
Consumer返回给Broker消费失败(常见
不管是因为什么情况了,是真的消费失败了,还是出现了异常了,还是明明消费成功了,但是你错误的返回了失败等等情况,只要你给 RocketMQ 返回的是 RECONSUME_LATER,那么消息就会重投,有重投就会有重复消费。
Consumer消费处理超时了(常见)
不只是返回失败的情况,如果消费方法执行时间过长,RocketMQ 可能判定消费者失联,也一样会重投消息。 那就和上面的情况一样了。
消息发重了(常见)
这种比较常见的,因为有的时候我们调用 MQ 发送消息的时候,因为网络抖动或者异常,我们会把一些实际成功的消息重发一遍,那么就会有两条一模一样的消息,那么对于消费者来说就可能会重复消费了。
广播模式
这不是重复消费,而是 RocketMQ 的广播模式特性,他就是会把一条消息发送给所有的消费者,但是如果大家处理的逻辑都一样, 那么和重复消费的表现是一样的。
RocketMQ如何保证消息的顺序性
和Kafka只支持同一个 Partition 内消息的顺序性一样,RocketMQ 中也提供了基于队列(分区)的顺序消费。即同一个队列内的消息可以做到有序,但是不同队列内的消息是无序的
当我们作为 MQ 的生产者需要发送顺序消息时,需要在 send 方法中,传入一个 MessageQueueSelector。
MessageQueueSelector 中需要实现一个 select 方法,这个方法就是用来定义要把消息发送到哪个 MessageQueue 的,通常可以使用取模法进行路由:
SendResult sendResult = producer.send(msg, new MessageQueueSelector() { @Override//mqs:该Topic下所有可选的MessageQueue //msg:待发送的消息 //arg:发送消息时传递的参数 public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) { Integer id = (Inte ...
普通消息、顺序消息的区别,在什么场景会用到
普通消息,就是很普通,没有什么特别的, 和顺序消息相比的话,就是消息发送到 MQ 后,消费者不保证严格按照发送顺序消费。消息可能会被乱序消费。
顺序消息是指生产者按照顺序发送消息,消费者也必需严格按顺序消费的消息。一般是通过绑定同一个分区来实现的。
顺序消息一般用在对顺序性有严格要求的场景中,比如是涉及到状态流转,尤其是那种状态流转的时间间隔很短的。
比如贷款的还款成功消息和结清消息。交易的确认收货消息和订单完结消息,基本都是同时发生的。如果系统是分别要处理这两个消息,那么可能就需要先处理确认收货,再处理订单完结,否则就会出问题的。
但是大多数情况下,我们用顺序消息的并不多,因为这只对收消息的应用有好处,而对发送消息的应用没有什么好处,反而增加了复杂性(而且还有吞吐量低、维护成本高等缺点)。而要做顺序消息,又需要发送者来做代码改造,所以很多系统都不愿意改,比如交易系统,不可能这么改的。
所以,实际上的大多数场景,并不一定会直接用MQ的顺序消息,而是倾向于消费者自己排序
前置状态判断
作为一个消费支付消息和发货消息的系统,我们可以基于这个 beforeStatus 来判断和我系统中的当前 ...
本地缓存
所谓本地缓存,就是和应用服务器在一起的缓存工具,将需要缓存的数据放到本地缓存中,可以大大的提升访问速度
数据结构
一般来讲,为了提升缓存的效率,通常采用 Key-Value 结构进行数据存储,也就是说,缓存中的数据保存和读取都需要有一个 Key,通过 Key 来读取固定的缓存的 Value
线程安全
本地缓存一定要考虑线程安全的问题,因为大多数情况下本地缓存都是一个全局可访问的变量,那么就会有多个线程同时访问,所以线程安全问题不容忽视
对象上限
因为是本地缓存,而本地内存中的数据是要占用 JVM 的堆内存的,所以内存是有上限要求的,如果无限存储,最终一定会导致 OOM 的问题
清除策略
为了避免 OOM 的问题,一般会考虑在缓存中增加清除策略,通过一定的手段定期的清理掉一些数据,来保证内存占用不会过大,常见清除策略主要有有 LRU(最近最少使用)、FIFO(先进先出)、LFU(最近最不常用)、SOFT(软引用)、WEAK(弱引用)等
过期时间
有了清除策略并不能保证百分百的可以删除数据,极端情况会会使得某些数据一直无法删除。这时候就需要有一种机制,能够保证某些 K-V 一定可以删除。通 ...
Nacos如何实现的配置变化客户端可以感知到
客户端与配置中心的数据交互方式其实无非就两种,要么推 ,要么就是拉
推的模式就客户端和服务端建立 TCP 长链接,当服务端数据发生变化,立即通过这个已经建立好的长连接将数据推送到客户端。长链接的优点是实时性,一旦数据变动,客户端立即就能感知到。但是缺点就是服务端需要维护大量的 TCP 连接,这会占用大量的内存和 CPU 资源,同时也容易受到网络抖动等因素的影响。
拉的模式就是客户端轮询,通过不断轮询的方式检查数据是否发生变化,变化的话就把数据拉回来。轮询的优点是实现比较简单,但弊端也显而易见,轮询无法保证数据的实时性,并且轮询方式对服务端还会产生压力。
在 Nacos 1.x 版本中采用的是长轮询,不是长连接,也不是轮询,是长轮询(Long Polling)。
其实就是把长连接和轮询综合了一下,就是说客户端发起轮询,但是不立即返回,而是 hold 一段时间,这段时间保持着一个有效连接,超时或者变化再返回,然后再发起一次轮询。
在 Nacos 2.0 中,采用 gRPC 长连接。
长轮询和长连接
长轮询是一种实现异步消息通信的机制,它通常用于客户端向服务器端请求某个资源时, ...
MySQL只操作同一条记录发生死锁
MySQL只操作同一条记录发生死锁数据库的锁锁的是索引,并不是记录
当我们在事务中,更新一条记录的时候,如果用到普通索引作为条件,那么会先获取普通索引的锁,然后再尝试获取主键索引的锁。那么这个时候,如果刚好有一个线程,已经拿到了这条记录的主键索引的锁后,同时尝试在该事务中去拿该记录的普通索引的锁。这时候就会发生死锁。
update my_table set name = 'hollis',age = 22 where name = "hollischuang";这个SQL会先对name加锁, 然后再回表对id加锁。-----select * from my_table where id = 15 for update;update my_table set age = 33 where name like "hollis%";以上SQL,会先获取主键的锁,然后再获取name的锁。
为了避免这种死锁情况的发生,可以在应用程序中设置一个规定的索引获取顺序,例如,只能按照主键索引->普通索引的顺序获取锁,这样就可以避免不 ...
Redis大Key问题
Redis大Key问题Big Key 是 Redis 中存储了大量数据的 Key,不要误以为 big key 只是表示 Key 的值很大,他还包括这个 Key 对应的 value 占用空间很多的情况,通常在 String、list、hash、set、zset 等类型中出现的问题比较多
其中 String 类型就是字符串的值比较大,而其他几个类型就是其中元素过多的情况
Redis 的 Big Key 可能存在以下几个危害:
影响性能:由于 big key 的 values 占用的内存会很大,所以读取它们的速度会很慢,会影响系统的性能。
占用内存: 大量的 big key 也会占满 Redis 的内存,让 Redis 无法继续存储新的数据,而且也会导致 Redis 卡住
内存空间不均匀:比如在 Redis 集群中,可能会因为某个节点上存储了 Big Key,导致多个节点之间内存使用不均匀。
影响 Redis 备份和恢复:如果从 RDB 文件中恢复全量数据时,可能需要大量的时间,甚至无法正常恢复。
搜索困难:由于大 key 可能非常大,因此搜索 key 内容时非常困难,并且可能需要花费较长 ...
ElasticSearch倒排索引
ElasticSearch倒排索引在 ElasticSearch 中,倒排索引是一种常用的索引结构,用于快速搜索文档中的某个词汇。
倒排索引的结构与传统的索引结构相反,传统的索引结构是由文档构成的,每个文档包含了若干个词汇,然后根据这些词汇建立索引。而倒排索引是由词汇构成的,每个词汇对应了若干个文档,然后根据这些文档建立索引。
对于一个包含多个词汇的文档,倒排索引会将每个词汇作为一个关键字(Term),然后记录下该词汇所在的文档编号(Document ID)及该词汇在文档中的位置(Term Position)。这样,当用户输入一个关键字时,就可以快速地查找到包含该关键字的文档编号,然后通过文档编号再查找到对应的文档内容。
倒排索引的优点在于它可以快速定位包含关键字的文档,而且可以支持复杂的搜索操作,如词组搜索、通配符搜索等。同时,由于倒排索引是由词汇构成的,因此在进行数据分析和统计时也非常有用。在 ElasticSearch 中,倒排索引是一种非常重要的索引结构,它被广泛应用于搜索引擎、日志分析、推荐系统等领域。
ElasticSearch
ElasticSearch数据模型
Elasticsearch 是基于文档的搜索引擎,它使用 JSON 文档来存储数据。在 Elasticsearch 中,相关的数据通常存储在同一个文档中,而不是分散在多个表中。
MySQL 是一个关系型数据库管理系统,它使用表、行和列的结构来组织数据。数据通过外键关系分散在多个表中。
查询语言
Elasticsearch 使用 Query DSL(Domain Specific Language),这是一种非常灵活的查询语言,基于 JSON,支持全文搜索、复合查询、过滤以及聚合等。
MySQL 使用 SQL(Structured Query Language),这是一种强类型和非常成熟的语言,专门用于查询和管理关系数据库。
全文搜索
Elasticsearch 的核心功能是全文搜索。它对数据进行索引时会自动建立全文搜索索引,使其在搜索大量文本数据时表现优异。
MySQL 虽然也提供了基本的全文搜索功能,但其主要设计目标是处理结构化数据的存储和查询,对全文搜索的支持不如 Elasticsearch 那样强大。
事务支持
Elasticsea ...
ROWNUM 和 ROW_NUMBER() 的区别
ROWNUM 和 ROW_NUMBER() 都是oracle中获取系统顺序分配为从查询返回的行的编号的,返回的第一行分配的是1,第二行是2,依此类推。
ROWNUM 是一个伪列,用来为查询结果中的每一行分配一个唯一的、递增的行号。 她返回的行号是按照查询结果的顺序分配的,而不依赖于特定的排序。它是在从数据库中提取数据时计算的,并且会在查询返回结果时就分配给每一行。
如果在没有使用ORDER BY的情况下使用 ROWNUM查询数据,返回的行号是根据数据在数据库中的物理存储顺序自动分配的。
如果使用 ROWNUM 与 ORDER BY 结合使用,ROWNUM 只会按查询返回的顺序分配行号,而不是按排序的结果分配。
ROW_NUMBER() 是一个窗口函数,它根据指定的排序规则为查询结果集中的每一行分配一个唯一的、递增的行号。 返回的行号是按照指定的排序顺序生成的。它是在结果集返回之前计算的,并且是基于 ORDER BY 子句中指定的排序规则分配的。
ROW_NUMBER() 会根据 ORDER BY 子句明确指定的列来分配行号,因此行号的顺序严格按照 ORDER BY 的顺序来。
...
