Clone
2
Home
Wonder edited this page 2025-10-24 13:01:48 +08:00
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

QA

Q1. 联合唯一索引 | 如何从数据库层面杜绝重复数据出现?

对于 thumb 表,使用联合唯一索引

CREATE UNIQUE INDEX idx_userId_blogId ON thumb (userId, blogId);

Q2. 循环依赖 | 为什么要在 BlogServiceImpl 导入 ThumbService 上加 @Lazy

  • 博客服务中需要使用点赞服务查询博客对应的点赞情况列表以返回对应视图。
  • 点赞服务中需要使用博客服务更新单条博客的点赞计数器。
  • 两个服务之间产生了循环依赖,Spring Boot 2.6 以后的版本默认不允许循环依赖,这里可以使用懒加载的方式避免这一问题。

Q3. 锁 | 点赞接口加锁对象是什么?对用户加锁还是对帖子加锁?

  • 加锁目的是为了避免用户并发请求造成数据不一致。
  • 不能对帖子加锁,因为帖子是全局的,加锁会导致其他用户无法点赞。
  • 因此需要对用户加锁,故而实际上是将每个用户的 id 当作锁。

Q4. 字符串对象锁 | 点赞接口的锁具体如何处理?

  • synchronized (("LOCK-USERID-" + loginUser.getId().toString()).intern())
  • 每个用户持有一个唯一 id,因此考虑把 id 对应的 String 常量池对象加锁。
  • 为了避免对程序中其他需要使用该字符串常量的地方产生影响,这里对字符串作出处理 "LOCK-USERID-" + loginUser.getId().toString()
  • 并且我们需要将字符串放到常量池中,调用 intern() 方法。

Q5. 序列化 | 对于 Redis 数据的存储使用序列化是怎么样的?

  • key 和 hash filed 使用 String 类型,value 使用 Object 类型。
  • value 为 Long 或者 Integer 类型时,优先进行以下操作——
    • 存储时转化为 String 类型
    • 取出时转化为 Long 或者 Integer 类型
    • (注意转化前需要先判空,避免空指针)

Q6. 类型转换 | Object 向 Long 的转化优化方式

  • 方法 A
    • Long.valueOf(object.toString())
    • 注意:object 为非数字字符串时会抛出 `NumberFormatException``
  • 方法 B
    • ((Number) object).longValue()
    • 注意:object 为非数字字符串时会抛出 `ClassCastException``
  • 比较
    • 方法 B 优于方法 A
      • 方法 A 需要调用 toString() 方法,有额外开销
      • 方法 B 直接调用 longValue() 方法,JVM 优化
      • 方法 B 抛出的异常容易定位问题。

Q7. 常量 | 定义常量的最佳方式?

  • "Do not use interfaces for constants. Interfaces are for defining types and behaviors, not for storing data."

    — Effective Java Item 18

  • 不建议选择 Interface 定义常量
  • 而应该选用 Class - public static final String 定义常量

Q8. Redis | 数据键值对是如何设计的?

使用了 Hash 的数据类型,遵循格式 Key-Filed-Value,以下是相关解释

  • Key
    • 前缀: "thumb:"
      public static final String USER_THUMB_KEY_PREFIX = "thumb:"
      
    • 业务键: "{userId}"
      • 从会话中获取,对于特定用户映射到同一个 Key
  • Filed
    • 业务域: "{blogId}"
      • 从请求参数中获取,对应具体的用户点赞相关业务的相关博客
  • Value
    • 类型: Long
    • 内容: 对应数据库中存储的 thumb_id,也就是 thumb 数据表的主键

Q9. MybatisPlus | thumb_id 的获取流程?

  • thumb_id 是 MyBatisPlus 自动生成的
    @TableId(type = IdType.AUTO)
    private Long id;
    
  • 执行点赞业务时,需要构造 Thumb 对象,补充 userId, blogId,通过 save 方法保存数据库中
  • 处理保存后, MyBatisPlus 会自动回填数据,执行主键回填,隐式地执行 setId() 方法