从零吃透 Elasticsearch + 分布式基础:倒排索引、DSL、Seata 分布式事务、Redis 分布式锁全记录

发布时间:2026/9/27 1:00:22

从零吃透 Elasticsearch + 分布式基础:倒排索引、DSL、Seata 分布式事务、Redis 分布式锁全记录 这周是我学习 Java 后端的一个分水岭。前六周学完了 Spring Boot、MySQL、Redis、微服务、消息队列感觉自己已经能写业务代码了。但这一周学完 ES 和分布式基础之后我才意识到真正的后端开发远不止 CRUD 那么简单。一、Elasticsearch为什么 MySQL LIKE 不够用1.1 从模糊查询说起之前做项目有个搜索框要查书名。我想当然地写了SELECT * FROM book WHERE title LIKE %Java%。数据量小的时候跑得挺欢等数据上了十万接口直接超时——全表扫描索引用不上。后来才知道MySQL 的 B 树索引是为精确查找和范围扫描设计的。你想查内容里包含哪些词B 树根本帮不上忙。这时候就该 Elasticsearch 出场了。1.2 倒排索引ES 的核心武器ES 用的是倒排索引。打个比方你有一本书传统做法是第 1 页写了什么、第 2 页写了什么正排倒排索引反过来是Java 这个词出现在第 1、5、10 页虚拟机出现在第 3、7 页词 → 页码列表。查询的时候把搜索词分词“Java 虚拟机分成Java和虚拟机”直接查倒排索引表拿到包含这些词的文档 ID根本不用扫全表。这就是为什么 ES 能在毫秒级返回结果。1.3 text 和 keyword两种字段类型ES 里字段类型分两种text写入时分词存的是一个个词条用于全文搜索用 match 查它keyword不分词整个值作为一个整体用于精确匹配、排序、聚合用 term 查它新手第一大坑用 term 去查 text 字段。text 字段写入时词条会被转成小写“Java存成了java”而 term 不分词拿大写Java原样去查当然查不到。正确做法是精确匹配走 keyword 子字段{term: {title.keyword: 完整书名}}。二、DSL 查询ES 里的 SQLES 的查询语言叫 DSLDomain Specific Language本质就是一段 JSON。查询的统一入口是GET /索引名/_searchbody 里放查询条件。2.1 match 和 term全文搜索 vs 精确匹配match查询词会被分词任意词条命中即匹配并按命中程度计算 _score相关性得分用于全文搜索term查询词不分词整体精确匹配用于状态、ID、枚举等精确过滤口诀搜内容用 match筛条件用 term。2.2 bool 查询四个子句各管一摊真实业务从来不只有一个条件。“价格 30-80、书名含 Java、排除某分类、最好还讲并发”——这种组合条件用 bool 查询子句含义参与算分吗must必须满足相当于 AND✅ 参与filter必须满足相当于 AND❌ 不参与should满足了加分不满足也行相当于 OR✅ 参与must_not必须不满足相当于 NOT❌ 不参与must 和 filter 的区别是面试高频中的高频两者都要求条件必须满足但 must 会计算 _scorefilter 不算分。不算分为什么反而是优点因为过滤结果可以被 ES 缓存而且省掉了算分开销——所以所有不需要按相关度排序的条件状态、时间范围、价格区间、分类一律放 filter性能更好。2.3 深分页问题用 from size 分页时ES 是分布式的数据散在多个分片上。你要第 100 页from990, size10ES 得让每个分片都把前 1000 条发给协调节点合并排序再从中挑出你要的 10 条——越往后翻白搬运的数据越多。所以生产上一般限制翻页深度更深的需求用search_after。三、Spring Boot 集成 ES三步走3.1 依赖和配置引入spring-boot-starter-data-elasticsearchyml 里配置 ES 地址spring:elasticsearch:uris:http://localhost:92003.2 实体类映射用Document注解把 Java 类映射到 ES 索引Field定义字段类型和分词器Document(indexNamebooks)publicclassBookDocument{IdprivateStringid;Field(typeFieldType.Text,analyzerik_max_word)privateStringtitle;Field(typeFieldType.Keyword)privateStringcategory;// ...}3.3 NativeQuery 三步流程复杂查询bool 组合、排序、高亮用ElasticsearchOperationsNativeQuery// 第一步构建 QueryNativeQueryqueryNativeQuery.builder().withQuery(q-q.bool(b-b.must(m-m.match(mq-mq.field(title).query(keyword))).filter(f-f.range(r-r.field(price).gte(JsonData.of(30)).lte(JsonData.of(80)))))).withPageable(PageRequest.of(page-1,size)).withSort(s-s.field(f-f.field(price).order(SortOrder.Asc))).withHighlightQuery(newHighlightQuery(newHighlight(List.of(newHighlightField(title))),BookDocument.class)).build();// 第二步执行查询SearchHitsBookDocumenthitsesOperations.search(query,BookDocument.class);// 第三步处理结果含高亮for(SearchHitBookDocumenthit:hits.getSearchHits()){BookDocumentbookhit.getContent();MapString,ListStringhighlightFieldshit.getHighlightFields();if(highlightFields.containsKey(title)){book.setTitle(String.join(,highlightFields.get(title)));}}记住这个流程NativeQuery.builder() 链式拼条件 → search 执行 → 遍历 SearchHit 处理高亮。3.4 数据同步MySQL 和 ES 怎么保持一致MySQL 是主存储增删改、事务都靠它ES 是搜索副本。两份数据怎么同步同步双写业务代码写完 MySQL 顺手写 ES简单但有失败不一致的风险监听 binlog用 Canal 等工具监听 MySQL 变更日志异步同步到 ES业务解耦、一致性更好大厂常用四、分布式事务CAP、BASE 和四种方案4.1 问题从哪来单体应用里一个Transactional就能保证多个操作要么全成功、要么全回滚。但微服务里订单在 order-service订单库库存在 inventory-service库存库Transactional只能管住自己这一个数据库——订单插进去了远程调用扣库存失败了订单怎么办跨服务记账怎么保证不出错就是分布式事务要解决的问题。4.2 CAP 定理三者最多满足两个CAP 定理说一个分布式系统一致性C、可用性A、分区容错性P三者最多只能同时满足两个。关键推论P 是没得选的。分布式系统里机器之间靠网络通信而网络故障是必然会发生的你不可能不允许网络分区。所以实际的选择是在 C 和 A 之间二选一CP保一致宁可拒绝服务也不能给错数据。ZooKeeper选主期间短暂不可用、银行转账AP保可用先给你响应数据之后再对齐。Eureka、Nacos、电商商品详情页选型原则资金、库存这类给错数据会出大事的场景保 C搜索、推荐、详情页这类给旧数据也无所谓的场景保 A。4.3 BASE 理论AP 的具体落地选了 AP等于承认数据可以暂时不一致。BASE 理论给出了答案Basically Available基本可用出问题时系统不整体挂掉但允许降级Soft State软状态允许数据存在中间状态不要求实时同步Eventually Consistent最终一致性不要求实时一致但最终所有数据会对齐一句话总结BASE 牺牲强一致性换取系统的高可用。4.4 四种分布式事务方案方案一致性性能业务侵入适用场景2PC两阶段提交强一致差同步阻塞低传统数据库 XA现在少用TCC强一致较高高要写三个接口资金、核心短链路Seata AT最终一致接近强中低一个注解一般业务最常用MQ 最终一致最终一致高中允许延迟的异步场景Seata AT 模式是我最想说的。它的卖点是对业务几乎零侵入——加一个注解搞定。工作原理分两阶段一阶段每个分支事务直接执行本地提交同时 Seata 自动拦截 SQL把修改前后的数据快照记到undo_log表里beforeImage 和 afterImage二阶段如果所有分支都成功 → 全局提交undo_log 异步删掉如果任何分支失败 → 全局回滚按 undo_log 里的 beforeImage 生成反向 SQL 补偿回去为什么一阶段直接提交还能保证一致因为 Seata 有全局锁被全局事务占用的行记录其他全局事务不能改防止了脏写。代码里就一个注解GlobalTransactional(rollbackForException.class)publicvoidcreateOrder(LonguserId,LongproductId,Integercount){orderMapper.insert(newOrder(userId,productId,count));inventoryFeign.deduct(productId,count);// 远程扣库存accountFeign.debit(userId,count*100);// 远程扣余额}任何一步抛异常TC 会驱动所有分支按 undo_log 回滚。五、分布式锁Redis 的三个坑和 Redisson5.1 为什么需要分布式锁单机场景synchronized锁住一个 JVM 内的共享资源就够了。但微服务部署了多个实例3 个 Pod 各自扣库存synchronized只能锁住自己这个 JVM3 个实例之间互相看不到——库存只剩 1 件3 个 Pod 同时判断还有货各自扣一次结果超卖了。你需要一把跨仓库的公共钥匙——谁拿到这把公共钥匙谁才能进仓库操作这就是分布式锁。5.2 Redis 实现分布式锁的三个坑基础实现SET key value NX EX secondsNX 表示不存在才设置保证互斥EX 表示过期时间防止死锁。必须原子操作不能用 SETNX EXPIRE 两步。坑 1不可重入。同一个线程再次获取锁会失败——自己把自己锁死了。解决用 Hash 结构记录持有者和重入次数。坑 2过期时间不好设。设短了业务没执行完锁就过期别人拿到锁设长了持有者宕机别人要等很久。解决看门狗自动续期——默认给锁 30 秒过期每 10 秒检查一次持有者还活着就续期到 30 秒。坑 3主从切换锁丢失。Redis 主节点刚加锁、还没同步到从节点就挂了从节点升级为主——别人可以拿到锁互斥性被破坏。解决RedLock 算法向 N 个独立 Redis 节点都加锁过半成功才算成功但争议大生产环境强一致场景用 ZooKeeper 更可靠。5.3 Redisson把三个坑全填了Redisson 是 Redis 官方推荐的 Java 客户端封装了分布式锁的所有坑RLocklockredisson.getLock(lock:stock:1);try{lock.lock();// 默认30s过期看门狗自动续期// 业务逻辑}finally{lock.unlock();}生产环境直接用 Redisson不用自己手写。六、分布式 ID雪花算法6.1 方案对比UUID128 位无序太长不适合做主键B 树插入性能差数据库自增简单但有瓶颈单点、性能差Snowflake 雪花算法趋势递增、不依赖中心、高性能6.2 雪花算法 64 位分配1 位符号位永远 0 41 位时间戳毫秒级可用 69 年 10 位机器 ID最多 1024 台 12 位序列号每毫秒 4096 个趋势递增时间戳在高位整体递增B 树插入友好不依赖中心每台机器根据 workerId 独立生成不需要协调高性能本地计算不依赖网络时钟回拨问题服务器时间被 NTP 同步回退导致生成的 ID 重复。解决方案等待时钟追上、或报错拒绝、或用美团 Leaf 等开源方案处理。七、项目实战设备管理平台这周学的东西在设备管理平台里都用到了ES 搜索设备搜索接口用 ESbool 查询组合关键词全文搜 状态过滤 时间范围过滤 高亮飘红数据同步设备主数据存 MySQL通过 Canal 监听 binlog 异步同步到 ES分布式锁设备绑定/解绑时用 Redisson 锁住 deviceId防止并发重复绑定分布式事务设备绑定要同时更新用户服务和设备服务用 Seata AT 保证强一致分布式 ID设备数据上报量巨大用雪花算法生成趋势递增的 report_id面试讲项目时可以说“强一致的场景我们用 Seata AT允许延迟的场景用 MQ 最终一致性选型依据是业务对一致性的容忍度”——这一句话就能体现你不是背八股而是真的做过取舍。八、本周感悟这周学完我最大的感触是后端开发远不止 CRUD。之前觉得会写 Spring Boot、会连数据库、会调接口就够了。但这周学完 ES 和分布式基础之后我才意识到真正的后端开发要考虑性能ES 倒排索引、要考虑一致性分布式事务、要考虑并发分布式锁、要考虑扩展性分布式 ID。每一个技术选型背后都是对业务场景的权衡。CAP 定理告诉你为什么做不到完美BASE 理论告诉你实践中怎么妥协四种分布式事务方案告诉你不同场景怎么选。这周的内容面试必问尤其是 CAP、Seata AT、Redis 分布式锁的三个坑、雪花算法。我把它们整理成博客也算给自己做个总结。下一周要学 Kafka 和 Flink搜广推方向的核心技术。继续加油。参考资料Elasticsearch 官方文档Spring Data Elasticsearch 参考文档Seata 官方文档Redisson 官方文档作者王俊翰原文链接一周从零吃透 Elasticsearch 分布式基础转载请注明出处
延伸阅读

更多相关文章

2026/9/20 22:31:17

Java枚举类详解:从基础到高级应用

1. Java枚举类基础概念解析 枚举(Enum)是Java 5引入的一种特殊数据类型,它允许开发者定义一组命名的常量集合。在实际开发中,我们经常遇到需要表示固定集合值的场景,比如星期几、订单状态等。使用枚举类可以完美解决这…

2026/9/22 9:23:30

2026年Facebook如何获得精准流量?从内容、账号到广告的完整打法

很多人在做 Facebook 营销时都会遇到一个问题: 每天坚持发帖子、发视频,但没有流量,没有互动,更没有精准客户。 其实问题往往不是 Facebook 没有流量,而是很多人的运营方式已经过时了。 Facebook 现在更注重用户兴趣匹…

2026/9/25 6:54:30

免费调用Kimi K3与GLM-5.2 API:低成本构建AI应用实战指南

最近在折腾AI应用开发时,发现很多开发者都在寻找免费、高性能且长文本能力强的模型API。无论是个人项目练手,还是初创团队验证想法,直接调用OpenAI或Claude的官方API成本压力都不小。而国内一些大模型虽然提供了免费额度,但在长上…

2026/9/27 0:55:48

3个核心动作拆解北京网络营销培训最佳实践避坑指南

3个核心动作拆解北京网络营销培训最佳实践避坑指南 很多老板一上来就问我:模板网站太丑不够用,能不能直接换个皮肤?我直接泼冷水:换皮解决不了根本问题。如果你还在为那些千篇一律的模板头疼,说明你还没真正搞懂 最佳实践 的逻辑。在北京做…

2026/9/27 0:55:48

WorkBuddy + Flask + SQLite:个人开发者日更建站实战指南

1. 为什么我选择 WorkBuddy Flask SQLite 这套组合1.1 从零建站这件事,工具选型决定了你后面要填多少坑做独立站这件事,我前前后后折腾过不少方案。最早用 WordPress,插件装了一堆,主题换了七八个,结果页面加载慢得离…

2026/9/27 0:55:48

Django请求响应与模板语法:从视图到模板渲染的全链路实战解析

写Django后端有一段时间了,从最早用函数视图拼HTML,到后来用类视图、DRF写接口,模板语法和请求响应这三块一直没绕开过。“模板语法、请求与响应”听起来像是Django入门三件套,但真正把这三样吃透,前端后端协作起来会顺…

2026/9/27 0:55:48

Linux 内核 CPU 拓扑:topology.c 与 sysfs 导出原理

跑过一次lscpu,看到输出里的 Socket、Core、Thread、NUMA node,你就已经间接遇到了 Linux 内核里的drivers/base/topology.c。它不是一个具体的设备驱动,而是设备驱动模型基础层里的一个“地图导出器”:把体系结构层算好的 CPU 拓…

2026/9/27 0:55:48

GTC 2026深度解读:AI工业化浪潮下的A股算力产业链三大主线

我参加过的行业交流里,被问得最多的问题其实不是"哪个模型更强",而是"GTC 2026之后,我手里的卡、我的项目、我的持仓方向到底该怎么调"。每逢黄仁勋站上舞台,整个产业链都会跟着抖三抖——这已经不是图形学大…

2026/9/27 0:50:48

wordpress4.9.7源码下载

新手入门WordPress 4.9.7:告别丑模板,3步搞定高颜值官网 做网站最怕什么?不是代码写不出来,而是装完模板打开一看,丑得让人想哭。那种千篇一律的蓝色渐变、生硬的方盒子布局,放在2024年简直像出土文物。很多新手入门…

2026/9/27 0:00:45

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/9/27 0:00:45

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/27 0:00:45

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/27 0:00:45

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/9/27 0:00:45

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/27 0:00:45

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/25 20:55:38

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/26 19:58:38

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/25 18:34:56

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑