Low Gravity

在这里,我们用算法解决问题,用代码表达思想

背景: 线上现场池出现偶发性的RejectedExecutionException, 第一时间检查线程池配置后未发现有明显异常, 在尝试调大队列长度后问题得到解决, 本文记录了排故的心路历程以及故障的真实原因; 代码已脱敏.

阅读全文 »

即时编译(Just-In-Time Compilation,简称JIT)是一种编译技术,它在代码即将首次执行时进行编译,因此得名“即时编译”。JIT是动态编译的一种特例。随着时间的发展,JIT的概念已经扩展,现在常被用来泛指动态编译;然而,狭义的JIT编译与更广泛的动态编译之间仍存在区别。动态编译(Dynamic Compilation)指的是在程序运行时进行编译,而静态编译(Static Compilation,也称事前编译,Ahead-Of-Time Compilation,简称AOT)则是在程序运行前完成编译。自适应动态编译(Adaptive Dynamic Compilation)也是一种动态编译技术,它先让程序以某种方式运行,收集信息后再进行编译,从而实现更高层次的优化。

阅读全文 »

Elasticsearch 虽提供强大搜索功能,但默认排序在复杂业务场景下渐显局限。电商需综合商品热度、评分等因素排序;新闻平台看重时效性与权威性;企业知识管理系统要考虑文档重要性等。Function Score Query 应运而生,它允许开发者依据业务规则自定义打分机制,实现精准个性化排序,以满足多样化需求,提升用户搜索体验与业务竞争力。

阅读全文 »

背景: IK 分词器作为一款广泛应用于中文文本处理的工具,在实际使用场景中,虽然提供了基本的分词功能,但随着业务需求的日益复杂和多样化,其原生功能逐渐显现出一定的局限性。例如,在特定领域的专业文本处理中,可能需要针对行业术语、品牌名称、产品型号等进行更精准的识别和分类;在大规模数据处理时,对分词效率和词典更新的实时性也提出了更高的要求。

为了满足这些不断增长的业务需求,提升文本处理的质量和效率,对 IK 分词器进行二次开发成为了一种必要的手段。通过深入研究 IK 分词器的源码,我们可以根据具体业务场景,定制个性化的分词逻辑,优化词典管理,改进分词算法,从而实现更符合实际需求的文本处理功能。

阅读全文 »

analysis, 中文意思分析,指的是es在文档发送之前对文档正文的执行过程,以添加到inverted index, 这一过程包含一下几个步骤:

  • 使用字符过滤器过滤字符,由char filter完成
  • 分词,将input按指定的规则分割为多个token, 由tokanizer完成
  • token过滤, 将上一步的tokens按一定规则进行处理, 由token filter完成
  • 存入索引
阅读全文 »

缓存作为一种介于应用程序和数据库之间的中间层,能够有效地存储频繁访问的数据,减少对数据库的直接查询操作,从而显著提高系统的性能。它通过将热点数据临时存储在快速访问的存储介质(如 Redis)中,使得后续的相同请求可以直接从缓存中获取数据,避免了重复的数据库查询开销,大大缩短了数据的响应时间。

然而,缓存的引入虽然带来了性能上的提升,却也引发了一系列新的问题,其中最为关键的就是缓存与数据库之间的数据一致性问题。由于缓存和数据库是两个独立的存储系统,它们的数据更新操作可能无法实时同步,导致在某些情况下,缓存中的数据与数据库中的数据不一致。这种不一致性可能会给用户带来困惑,影响业务的正常运行,例如用户可能获取到过期或错误的数据,进而影响用户体验和业务决策的准确性。

因此,在设计和实现包含缓存的系统架构时,如何确保缓存与数据库之间的数据一致性成为了一个亟待解决的重要问题。这需要深入分析各种可能导致数据不一致的场景和原因,研究并制定有效的治理方案,在保证系统性能的前提下,尽可能降低数据不一致出现的概率,以满足业务对数据准确性和可靠性的要求。

阅读全文 »

因为可见性问题导致处理器不同核心看到的内存操作顺序不一致,从而看起来就像是指令被重排了一样

JMM在编译器重排阶段, 会禁止特定类型的编译器重排, 在处理器重排序阶段,通过在指令之间插入内存屏障来禁止特定类型的处理器重排, 从而确保了在不同的编译器和不同的处理器平台上,不会应为重排序规则不一致导致非预期的运行结果

现代处理器与内存进行数据交互,会先将数据写到自己的缓冲区中, 每个处理器都有自己的缓冲区, 这种特性就会导致缓冲区中的数据和内存的数据存在不一致, 例如核心A执行两条指令, 指令1是更新x的值, 指令2是读取y的值, 核心A更新了x并写入缓冲区,然后去主存读了y; 核心B执行两条指令, 指令1是更新y的值, 指令2是读取x的值, 核心B更新了y的值写入缓冲区, 然后去主存读了x的值, 因为两个核心的缓冲器都还未刷新,所以他们读到的都是旧值, 或者是只刷新了一个缓冲区; 这些都会导致在指令层面看起来就像是发生了指令重排一样, 其实核心是因为可见性问题,所以也会有人将这种现象称之为内存系统指令重排。

阅读全文 »

在许多业务场景中,任务的执行需要与时间紧密关联。例如,在电商领域,订单在生成后的一段时间内未支付则需要自动取消,以释放库存并管理订单状态;新店铺创建后若长时间未上传商品,需及时提醒商家以促进平台活跃度;企业财务系统中,账单在规定期限内未支付则要进行自动结算,确保财务流程的顺畅。这些场景的共同点是都涉及到在特定时间点或时间段后触发相应的操作,对时间的准确性和任务的可靠性要求极高。

传统的解决方案如定时任务,通过定期轮询数据库来检查任务是否满足执行条件。然而,在数据量较小且对时间精度要求不高的情况下,这种方式或许可行。但当面对大规模数据和高时效性要求时,定时任务的弊端就凸显出来。它需要频繁地查询数据库,这不仅会给数据库带来巨大的压力,影响系统的整体性能,还可能由于查询间隔的限制导致任务执行的延迟,无法满足业务对实时性的严格要求。例如,在电商大促期间,订单量可能瞬间暴增到数百万甚至上千万,如果使用定时任务来检查未支付订单,可能在一秒内无法完成所有订单的检查,导致部分订单未能及时关闭,影响库存管理和用户体验。

在这样的背景下,消息队列技术应运而生,为解决这类复杂的消息处理需求提供了新的思路和方法。RabbitMQ 作为一款功能强大的消息队列中间件,以其出色的可靠性、灵活性和扩展性,在众多企业的消息处理架构中占据重要地位。它能够实现消息的异步传输,解耦系统组件,提高系统的可伸缩性和响应能力。而延时队列作为 RabbitMQ 的一种特殊应用场景,能够精准地控制消息的延迟处理时间,为上述各种业务场景提供了更为高效、可靠的解决方案,成为企业构建复杂业务逻辑和优化系统性能的关键技术之一。

阅读全文 »

RabbitMQ是流行的开源消息队列系统,使用erlang语言开发,由于其社区活跃度高,维护更新较快,性能稳定,深得很多企业的欢心。

为了保证订单业务的消息数据不丢失,需要使用到RabbitMQ的死信队列机制,当消息消费发生异常时,将消息投入死信队列中。但由于对死信队列的概念及配置不熟悉,导致曾一度陷入百度的汪洋大海,无法自拔,很多文章都看起来可行,但是实际上却并不能帮我解决实际问题。最终,在官网文档中找到了我想要的答案,通过官网文档的学习,才发现对于死信队列存在一些误解,导致配置死信队列之路困难重重。

于是本着记录和分享的精神,将死信队列的概念和配置完整的写下来,以便帮助遇到同样问题的朋友。

阅读全文 »
0%