Understanding the CAS Spin Pattern in Java Through Random UPDATING 

Do you understand this snippet? do { oldseed = seed.get(); newseed = (oldseed * ...) & mask; } while (!seed.compareAndSet(oldseed, newseed)); // ← CAS Level 0: First understand why a “variable” is dangerous in multithreading Suppose there’s a variable seed = 100, and two threads want to change it at the same time: Thread A: reads seed=100 → computes new value 200 → writes back seed=200 Thread B: reads seed=100 → computes new value 300 → writes back seed=300 Here’s the problem — both read 100, each computes on its own, and whoever writes later wins. A’s result is overwritten by B, A’s work is wasted, and the program has no idea anything went wrong. ...

2026-06-06 09:40:20 PM · 4 min

A Close Look at Common Caching Strategies UPDATING 

The Three Cache Brothers Cache Penetration What it is: a flood of requests querying data that doesn’t exist in the database. The cache has nothing, so it keeps hammering the database. Prevention: Cache null values Even when the database finds nothing, put an empty marker in the cache (with a short TTL, e.g. 2 minutes; only after that TTL expires can the database be queried again) The next time the same id comes in, it’s blocked directly Pros: effectively intercepts large numbers of penetration requests Cons: A malicious attack with many different non-existent keys fills the cache with useless data and wastes memory It delays data consistency; new data has to wait for the cache to expire Bloom filter (recommended) At startup, put all legitimate ids into the Bloom filter If the Bloom filter says no, it really doesn’t exist Pros: No high-memory-usage risk No data-consistency risk Cons: There’s a tiny false-positive rate Insertions and deletions need maintenance; when data updates, the Bloom filter must be updated in sync Rate limiting and validation at the interface layer Intercept at the API gateway or Controller layer Parameter validation, rate limiting, and degradation Mutex-based rebuild A mutex mainly solves cache breakdown (a hot key expiring), but in the cache-empty-object scenario, if there are many concurrent requests for a non-existent key, a lock can be used Each access lets one thread query the DB while the others wait Big companies’ practice ...

2026-05-05 10:46:44 PM · 3 min

The Fundamentals You Need to Build a Chat Room UPDATING 

The TCP Three-Way Handshake Client — Server Purpose of the three-way handshake: the client’s send and receive are both fine, and the server’s send and receive are both fine. First handshake: the client sends SYN (synchronize request) Client: I know nothing, so I’ll send out a SYN message and see if anyone receives it. If no one replies, I send it a few more times (timeout retransmission). At this moment, what the client knows is: I sent it, but I don’t know whether anyone received it ❌ Can I receive messages? Unknown ❌ Does the other side exist? Unknown ❌ Second handshake: the server replies SYN+ACK (synchronize + acknowledge) The server received the client’s SYN. ...

2026-04-03 11:45:26 AM · 17 min

Why the Backend Sometimes Needs to Maintain a Refresh_Tokens Table

The Normal JWT Request Flow sequenceDiagram participant User as User participant Frontend as Frontend (browser/app) participant Auth as Auth server participant Backend as Backend API server Note over User,Backend: 1. Login phase User->>Frontend: enter username/password Frontend->>Auth: POST /login (credentials) Auth->>Auth: verify credentials Auth-->>Frontend: return access_token + refresh_token Frontend->>Frontend: store tokens (memory/localStorage) Frontend-->>User: login successful Note over User,Backend: 2. Normal request phase User->>Frontend: request a protected resource Frontend->>Backend: GET /api/resourceAuthorization: Bearer access_token Backend->>Backend: verify access_token signature and expiry Backend-->>Frontend: return the requested resource Frontend-->>User: display data Note over User,Backend: 3. Access token expires User->>Frontend: keep requesting Frontend->>Backend: GET /api/resourceAuthorization: Bearer access_token (expired) Backend-->>Frontend: 401 Unauthorized (token expired) Frontend->>Frontend: detects 401, triggers refresh logic Note over Frontend,Auth: 4. Token refresh phase Frontend->>Auth: POST /refreshrefresh_token Auth->>Auth: verify refresh_token Auth-->>Frontend: return a new access_token (optionally a new refresh_token) Frontend->>Frontend: update the stored access_token Frontend->>Backend: retry the original request (new access_token) Backend-->>Frontend: return the requested resource Frontend-->>User: display data Why You Can’t Rely on JWT Alone Once a refresh token is issued and the backend doesn’t store it, it becomes an uncontrollable long-term pass You can’t forcibly log a user out You can’t log out a single device You can’t tell whether a token has been stolen (an attacker who gets the refresh token can keep refreshing the access token forever) You can’t implement session management The Flow After Using a refresh_tokens Table sequenceDiagram participant User as User participant Frontend as Frontend participant Auth as Auth server participant DB as Database (refresh_tokens table) participant Backend as Backend API server Note over User,DB: 1. Login phase (issue token + persist) User->>Frontend: enter username/password Frontend->>Auth: POST /login Auth->>Auth: verify credentials Auth->>DB: generate a unique refresh_token_idINSERT INTO refresh_tokens(user_id, token_hash, expires_at, device_info, ip_address, revoked) DB-->>Auth: insert successful Auth->>Auth: generate access_token + refresh_token(refresh_token contains the id reference) Auth-->>Frontend: return access_token + refresh_token Frontend->>Frontend: store tokens Frontend-->>User: login successful Note over User,Backend: 2. Normal request (same as before) User->>Frontend: request a resource Frontend->>Backend: GET /api/resourceAuthorization: Bearer access_token Backend->>Backend: verify access_token Backend-->>Frontend: return the resource Note over Frontend,DB: 3. Access token expires → refresh Frontend->>Backend: GET /api/resource (access_token expired) Backend-->>Frontend: 401 Unauthorized Frontend->>Auth: POST /refreshrefresh_token Note over Auth,DB: 4. Refresh verification (multi-step checks) Auth->>Auth: parse refresh_token, extract token_id Auth->>DB: SELECT * FROM refresh_tokensWHERE id = token_id DB-->>Auth: return the record Auth->>Auth: verification checklist: Note over Auth: ✅ does token_hash match✅ is it expired (expires_at > now())✅ is it revoked (revoked = false)✅ is the user still valid✅ does device info match (optional) alt all checks pass Auth->>DB: UPDATE refresh_tokensSET last_used_at = now(), last_used_ip = current_ipWHERE id = token_id Auth->>Auth: generate a new access_token(optional: extend refresh_token validity) Auth-->>Frontend: return the new access_token Frontend->>Frontend: update access_token Frontend->>Backend: retry the original request (new token) Backend-->>Frontend: return the resource else checks fail Auth-->>Frontend: 401/403 (refresh failed) Frontend->>Frontend: clear all tokens Frontend->>User: redirect to the login page end Note over User,DB: 5. Explicit logout User->>Frontend: click logout Frontend->>Auth: POST /logoutrefresh_token Auth->>DB: UPDATE refresh_tokensSET revoked = trueWHERE id = token_id Auth-->>Frontend: logout successful Frontend->>Frontend: clear local tokens Frontend-->>User: logged out Note over User,DB: 6. Security scenario: password change User->>Frontend: change password Frontend->>Auth: POST /change-password Auth->>DB: UPDATE refresh_tokensSET revoked = trueWHERE user_id = current_user_id Note over DB: revoke all of the user's refresh_tokens(force all devices to log in again) Auth-->>Frontend: password change successful Frontend->>Frontend: clear local tokens Frontend-->>User: please log in again

2026-03-02 08:07:07 PM · 3 min

Microservice Auth System: Architecture Walkthrough and Interview Prep UPDATING 

Tech stack: Spring Boot 3 · Spring Cloud Alibaba · OpenFeign · JWT · Gateway · Nacos How to use this document When you talk about a project in an interview, the worst thing you can do is start from code details. The right order is: First explain what problem it solves → then the overall architecture → then walk through it by request flow → finally handle the deep-dive questions. ...

2026-01-26 06:05:16 PM · 10 min

On What a Hassle Login Is UPDATING 

Everyone who has written a backend, sooner or later, has to fight a hard battle with “login.” It looks like a small feature — a username, a password, a button — but anyone who has actually built it knows this is the part of the whole system with the deepest pits, the most painful changes, and the most fatal failures. It’s a hassle not because the technology is hard, but because it sits right at the intersection of three parties’ interests: users want convenience, product wants growth, and security wants an airtight defense. These three are naturally at odds. Every inch you move toward one, the other two start crying out. ...

2025-12-26 03:56:40 PM · 13 min

The Incompatibility Between PostgreSQL and Java's LocalDateTime UPDATING 

Java’s LocalDateTime and PostgreSQL’s time types “aren’t talking about the same kind of time.” First, get clear on PostgreSQL’s two time types TIMESTAMP → without time zone, just a bare time "2026-06-25 10:00:00" TIMESTAMPTZ → with time zone, stored internally as UTC, converted to the session time zone on query On the Java side LocalDateTime → no concept of a time zone, just a bare time ZonedDateTime → with time zone OffsetDateTime → with an offset (e.g. +08:00) Instant → a UTC timestamp Why the error happens The PostgreSQL JDBC driver (especially newer versions 42.x+) is very strict about type matching: ...

2025-10-25 12:55:49 PM · 2 min

Swagger 2 vs. Swagger 3 Annotation Comparison Table UPDATING 

In the Spring Boot ecosystem, the annotations changed a great deal between Swagger 2.0 (typically using the Springfox dependency) and Swagger 3.0 (typically using the Springdoc-openapi dependency, based on the OpenAPI 3 spec). Below is a complete correspondence table of the common annotations in Swagger 2.0 vs. Swagger 3.0 (OpenAPI 3): 1. Core annotation correspondence table Description Swagger 2.0 annotation (io.swagger.annotations) Swagger 3.0 annotation (io.swagger.v3.oas.annotations) Notes Mark a controller class @Api(tags = "User API") @Tag(name = "User API") 3.0 removed the description attribute; use name uniformly Mark an API method @ApiOperation(value = "Get user") @Operation(summary = "Get user") In 3.0 value became summary Request/entity class @ApiModel(value = "User object") @Schema(description = "User object") 3.0 greatly simplified this; use @Schema uniformly Entity class property @ApiModelProperty(value = "Name") @Schema(description = "Name") As above, merged into @Schema Ignore a property @ApiModelProperty(hidden = true) @Schema(hidden = true) Ignore a whole class/method @ApiIgnore @Hidden For endpoints or parameters you don’t want exposed in docs 2. Request-parameter annotation correspondence table For method parameters (URL path parameters, query parameters, etc.), 3.0 introduced a more structured configuration: ...

2025-09-25 09:06:35 AM · 2 min

SCA 2023.X — Troubleshooting and Fixing the Nacos Bootstrap Config Failure

Issue source: spring-cloud-alibaba#3931 Affected versions: spring-cloud-alibaba 2023.0.1.3+ 1. Problem Description In Spring Cloud Alibaba 2023.X, placing Nacos config (including extension-configs, shared-configs, etc.) in bootstrap.yml / bootstrap.properties causes the config center’s content to fail to load properly, even though the logs show the bootstrap file itself was read. Moving the same config to application.yml makes everything work again. 2. Root Cause flowchart TD A[bootstrap.yml is read] --> B{SCA version check} B -- 2023.0.1.2 and earlier --> C[✅ Nacos config center loads normally] B -- 2023.0.1.3 and later --> D[❌ extension-configs / shared-configs fail] D --> E[Root cause: SCA 2023.0.1.3 changed the config-load priority mechanism] E --> F[Nacos PropertySource registered in the bootstrap phase is overwritten or discarded by later steps] In short: SCA 2023.0.1.3 made a backward-incompatible internal change, causing the Nacos extension config in bootstrap.yml to be “dropped” in the loading chain, while config in application.yml takes the new path and is unaffected. ...

2025-07-24 10:40:26 PM · 3 min

Some Common Nacos Configurations UPDATING 

bootstrap config bootstrap.yaml server: port: 10888 tomcat: uri-encoding: UTF-8 spring: profiles: active: dev application: name: archive-service cloud: nacos: config: file-extension: yaml shared-configs: - data-id: shared-spring.yaml refresh: false - data-id: shared-redis.yaml refresh: false - data-id: shared-mybatis.yaml refresh: false - data-id: shared-logs.yaml refresh: false - data-id: shared-feign.yaml refresh: false - data-id: shared-logs.yaml # shared logging config refresh: false # - data-id: shared-feign.yaml # shared feign config # refresh: false lia: jdbc: database: tb_archive bootstrap-dev.yaml spring: cloud: nacos: server-addr: 192.168.2.115:8848 # nacos registry discovery: namespace: f923fb34-cb0a-4c06-8fca-ad61ea61a3f0 group: DEFAULT_GROUP ip: 192.168.2.115 logging: level: asia.liminality: debug nacos config shared-spring.yaml spring: jackson: default-property-inclusion: non_null main: allow-bean-definition-overriding: true mvc: pathmatch: # Fixes the exception: swagger Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException # Because Springfox's path matching is based on AntPathMatcher, while Spring Boot 2.6.X uses PathPatternMatcher matching-strategy: ant_path_matcher shared-redis.yaml spring: redis: host: ${lia.redis.host:192.168.2.115} password: ${lia.redis.password:github} lettuce: pool: max-active: ${lia.redis.pool.max-active:8} max-idle: ${lia.redis.pool.max-idle:8} min-idle: ${lia.redis.pool.min-idle:1} max-wait: ${lia.redis.pool.max-wait:300} shared-mybatis.yaml MySQL spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://${sh.jdbc.host:127.0.0.1}/${sh.jdbc.database}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false username: ${lia.jdbc.username:root} password: ${lia.jdbc.password:794211} mybatis-plus: configuration: default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler global-config: db-config: logic-delete-field: deletedAt logic-not-delete-value: "null" logic-delete-value: "now()" id-type: assign_id insert-strategy: not_null update-strategy: not_null PostgreSQL spring: datasource: driver-class-name: org.postgresql.Driver url: jdbc:postgresql://${lia.jdbc.host:192.168.2.115}:${lia.jdbc.port:5432}/${lia.jdbc.database}?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai username: ${lia.jdbc.username:postgres} password: ${lia.jdbc.password:github} mybatis-plus: configuration: default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler global-config: db-config: logic-delete-field: deletedAt logic-not-delete-value: "null" logic-delete-value: "now()" id-type: assign_id insert-strategy: ignored update-strategy: ignored select-strategy: not_null shared-logs.yaml logging: pattern: dateformat: HH:mm:ss.SSS console: "%clr(%d{${LOG_DATEFORMAT_PATTERN}}){faint}-[${hostname}][%X{requestId:-sys}] %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n" file: "%d{${LOG_DATEFORMAT_PATTERN}}-[${hostname}][%X{requestId:-sys}]-${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%15.15t] %-40.40logger{39} : %m%n" file: path: "logs/${spring.application.name}" shared-feign.yaml feign: client: config: default: # the default global config loggerLevel: BASIC # log level; BASIC is the basic request and response info httpclient: enabled: true # enable Feign's HttpClient support max-connections: 200 # max connections max-connections-per-route: 50 # max connections per route sentinel: enabled: true

2025-06-24 07:01:02 PM · 2 min