月度记录-2024-11月

70 阅读8分钟

1. spring事务失效的场景

  • 内部方法调用

  • 如果在同一个类内部直接调用带有 @Transactional 注解的方法,事务不会生效。因为此时是直接调用,绕过了代理,导致事务的开启和提交/回滚逻辑不被执行。

  • 非 Spring 管理的对象:

  • 如果你在 Spring 管理的类中调用了一个非 Spring 管理的对象的方法,且该方法使用了 @Transactional 注解,事务不会生效。因为只有 Spring 创建的代理对象才能正确处理事务。

  • 抛出非运行时异常:

  • 默认情况下,只有运行时异常(RuntimeException)和错误会导致事务回滚。如果方法抛出一个受检查的异常(Exception),事务不会回滚,除非在 @Transactional 注解中显式指定 rollbackFor 属性。

  • 事务传播行为配置不当:

  • 事务传播行为(propagation)控制事务的边界。如果在一个已存在的事务中调用另一个事务方法,而第二个方法的传播行为设置为 REQUIRES_NEW,会导致新事务被创建并独立于原事务。这可能导致原事务中的操作被回滚,而新事务的操作不受影响。

  • 手动管理事务:

  • 如果在 @Transactional 方法中手动管理事务(例如,使用 TransactionTemplate 或 TransactionManager),而没有正确控制事务的边界,可能导致预期的事务操作不生效或不一致。

  • Spring 代理问题:

  • 如果类没有正确地实现接口(对于 JDK 动态代理)或方法没有被 public 修饰(对于 CGLIB 代理),可能导致事务失效。Spring 代理仅对 public 方法有效。

  • 使用非一致性数据源:

  • 如果在同一个事务中,访问了多个数据源,而这些数据源没有进行一致性管理(如使用 XA 事务),会导致事务管理的复杂性和潜在的数据不一致性。

  • 事务超时:

  • 如果事务执行超出了配置的超时时间,事务会被强制回滚,导致事务失效。可以通过 @Transactional 的 timeout 属性设置超时时间。

2. Redis 有序集合(Sorted Set)

Redis 有序集合(Sorted Set,简称 ZSet)是一种特殊的集合,它不仅包含元素,还给每个元素关联了一个分数(score)。这些元素会根据分数进行排序,且分数可以是浮点数。Redis 提供了丰富的 API 来操作有序集合,使其非常适合需要按顺序检索数据的场景,如排行榜、优先级队列等。

3. Elasticsearch geo_point

geo_point 是 Elasticsearch 中用于存储地理位置数据的字段类型。它可以存储地理坐标(经度和纬度),并支持各种地理位置相关的操作,例如地理位置查询、距离计算、聚合等。

geo_point 类型专门用于表示地理位置,通常由 经度(longitude)和 纬度(latitude)组成。Elasticsearch 使用 geo_point 类型来存储和查询地理位置数据。

支持:范围查询、距离查询、点查询、多边形查询、最近距离查询等。

4. MyBatis-Plus自定义字段的转换规则

允许自定义如何处理数据库字段与 Java 类型之间的转换。通过这种方式,你可以在字段的插入和查询过程中进行特定的转换,比如对某些值进行校验、转换、处理等操作。

比如数据库时null,你想让他返回0,还是null?都可以自定义。

@TableName(value = "xxx", autoResultMap = true) @TableField(typeHandler = IntegerZeroTypeHandler.class) public class IntegerZeroTypeHandler extends BaseTypeHandler {}

5. 多个字段not in 结合元组

非所有数据库都支持多列元组,比如 MySQL 在早期版本中不支持,但在 MySQL 8.0 中增加了对多列元组的支持。

SELECT * FROM zzz WHERE (jobId, userId) NOT IN ((1, 11), (1,22));

6. mapstruct

@Mapper(componentModel = MappingConstants.ComponentModel.SPRING) // 它告诉 MapStruct 生成的映射器类将以 Spring Bean 的形式进行管理。通过 Spring 的依赖注入机制使用它。

7. kibana AutoIndent 数字改变

"id":{"value":1855808218566033408,"boost":1.0}

例如这个,格式化后就会变为1855808218566033400,这怎么查得出来。

估计是 JavaScript 数字类型的精度限制导致的。

避免精度丢失的方式:可以将大数字存储为字符串,例如:"id": {"value": "1855808218566033408", "boost": 1.0}。

8. 怎么保证数据库和es数据的一致性

  • 双写(同步写入数据库和 Elasticsearch)。

  • 异步消息队列(基于事件驱动的最终一致性)。

  • Change Data Capture (CDC)(基于数据库变更日志的实时同步)。

  • 批量更新(消息队列,周期性同步)。

以上几种方案,如果实时性要求高应该使用双写,但是双写可能导致数据不一致,要考虑到。

其次是批量更新,可以加一个消息表,配合消息队列,可以实现最终一致性,但实时性差一点。

我觉得吧,如果真是特别重要的场景,可以双写+批量更新。都用,大部分情况数据是一致的,就算不一致时间也很短。

9. ES中RefreshPolicy

request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); 是在 Elasticsearch 中用于控制索引刷新策略的一个设置,常用于在进行文档写入(如 index、update、delete)时,指定刷新策略。

在 Elasticsearch 中,刷新 是将内存中的数据(称为 translog)写入到磁盘上的一个过程,这样新写入的数据才能被搜索到。刷新通常会在后台自动进行,但是可以通过设置 refresh 参数来控制刷新时机。

主要选项:

  1. WriteRequest.RefreshPolicy.NONE:不执行刷新操作。这是默认行为,通常在高吞吐量场景下使用,因为频繁刷新可能会导致性能问题。
  2. WriteRequest.RefreshPolicy.IMMEDIATE:写操作后立即刷新索引。这会确保数据在写入后可以立即被搜索到,但会有性能开销,因为每次写入后都会进行刷新。
  3. WriteRequest.RefreshPolicy.WAIT_UNTIL:等待刷新直到当前写操作完成后进行刷新。这种方式在某些情况下可以平衡写入性能和刷新性能,保证数据在索引操作后能够被搜索到。

总结:

  • WAIT_UNTIL 适用于你需要确保当前写操作的数据能被及时搜索到,但又不想频繁进行刷新(因为频繁刷新可能对性能有不利影响)。比如,在一些高并发写入场景下,你可能希望等所有当前的写入操作完成后再进行一次刷新。

10. OpenObservability(OpenObserves)

并不是一个固定的产品或技术名词,而是指一类与 开放式可观察性 相关的工具和方法论,它通常包括对应用程序、系统、服务和基础设施的监控、跟踪、日志记录等各种数据的收集、处理和分析。目标是提升对分布式系统和微服务架构的洞察力,以便能够快速诊断和解决问题。

目前,开放可观察性领域有很多项目和标准,其中最著名的是 OpenTelemetry 和 OpenMetrics,它们是帮助组织构建和集成可观察性基础设施的重要框架。

OpenObservability的组成部分

开放可观察性通常包含以下几大组成部分:

  1. 指标(Metrics)

  2. 日志(Logs)

  3. 分布式追踪(Tracing)

  4. 可视化(Visualization)

  5. 警报和通知(Alerts and Notifications)

11. OpenTelemetry

OpenTelemetry 是一个开源项目,旨在为分布式系统提供统一的、标准化的可观察性框架。它通过收集、处理和导出应用程序的日志、指标和分布式追踪数据,帮助开发人员和运维人员理解、监控和诊断系统的健康状况和性能瓶颈。OpenTelemetry 是一个跨平台的框架,支持多种编程语言(如 Java、Go、Python、JavaScript 等),并可以与多种监控工具和后端系统(如 Prometheus、Jaeger、Zipkin、Elasticsearch 等)集成。

OpenTelemetry的核心组件

OpenTelemetry 主要由三个核心组件组成:

OpenTelemetry的主要功能

分布式追踪(Tracing)、度量(Metrics)、日志(Logs)

OpenTelemetry其实并不能存储日志信息吗?只能导入到其他地方存储,比如es?

OpenTelemetry 本身并不负责存储日志信息。它的主要任务是 采集、处理和导出 可观察性数据(如追踪、度量和日志),而不是直 接存储这些数据。它提供了一种标准化的方式来收集、处理和导出日志、追踪和度量数据,但将这些数据存储起来的工作通常由其他工具和平台(如 Elasticsearch、Prometheus、Jaeger、Zipkin 等)来完成。

OpenTelemetry 提供了多种 导出器,用于将数据导出到第三方存储系统。常见的导出器包括:

  • Elasticsearch Exporter:将日志数据导出到 Elasticsearch,以便存储和查询。
  • Prometheus Exporter:将度量数据导出到 Prometheus。
  • Jaeger/Zipkin Exporter:将分布式追踪数据导出到 Jaeger 或 Zipkin。
  • 自定义 Exporter:你可以实现自定义导出器,将数据导出到任何其他系统。

12. 日志json格式

记录json格式的日志,方便后续分析日志。

13. Pretty JSON Log

解决idea控制台输出json日志,看异常麻烦的问题。

14. hotseconds

一款热部署插件,可以远程修改jar内的文件,解决jar包启动项目,使用不了idea热部署的问题。

15. idea虚拟外键

画UML图的时候用到了,可以方便画图,很好的描述各个表之间的关系。

现在互联网项目都不用外键的,所以idea生成UML图展现不出来表与表之间的关系,配置虚拟外键,可以展示这个关系。