Raymond Lam's Technical Blog

website·Indexed 29 days ago

https://raymondlam1.github.io

A personal technical blog focusing on Java runtime, garbage collection, and high-performance Java persistence. The site includes reading notes on the Go programming language, Vim guides, and discussions on Domain-Driven Design (DDD), Apache Calcite, and monitoring tools like Grafana and Prometheus.

Tokens
22.4K
Snippets
91
Records
143
Agent score
75%

What's inside Raymond Lam's Blog

  1. Overview of Apache SeaTunnel for distributed data integration

    Apache SeaTunnel is a high-performance distributed data integration platform designed for real-time synchronization of massive datasets. It is capable of stably synchronizing tens of billions of records daily and is used in production by nearly a hundred enterprises.
    # Source code available at: https://github.com/apache/seatunnel
  2. Overview of Apache Calcite for dynamic data management

    Apache Calcite is a dynamic data management framework that provides core database management capabilities, including SQL parsing, SQL validation, SQL query optimization, SQL generation, and data connection queries.
    # Source code available at: https://github.com/apache/calcite/
  3. Implement DDD using Hexagonal Architecture

    Domain-Driven Design (DDD) is a modeling philosophy used to analyze systems starting from use case diagrams to identify domain services (e.g., login, ordering, payment). Hexagonal Architecture is the technical implementation pattern used to realize DDD, preventing the logic clutter common in MVC by separating the domain from external infrastructure via an Anti-Corruption Layer (ACL).
  4. Understand Vim's basic command grammar

    Vim commands follow a simple grammatical structure: verb + noun.

    • Verbs (Operators): Actions to perform on text.
    • Nouns (Motions/Text Objects): The target or scope of the action.

    Combining these allows you to 'speak' to the editor. For example, to yank (verb) to the end of the line (noun), you use y$. To delete (verb) the next word (noun), you use dw.

  5. Structure a DDD-based system architecture

    A DDD architecture replaces the traditional MVC flow with a more decoupled structure consisting of the following layers:

    • Trigger Layer: Handles external entry points such as HTTP, RPC, Jobs, and MQ. It focuses on request encapsulation, error codes, and exceptions, delegating business logic to the Case or App layers.
    • Case Layer: Responsible for service orchestration of complex business flows.
    • App Layer: Serves as the application entry point.
    • Domain Layer: The core of the system containing 'rich domain models' (充血模型). It includes:
      • Entities, Value Objects, and Aggregates: The core data and logic structures.
      • Domain Services: Specific business logic (e.g., login validation).
      • Adapters: Ensure that data required by the domain is fetched from external sources (DB, Cache, APIs) without leaking external dependencies into the domain (ACL design).
    • Infrastructure Layer: Implements the interfaces defined by the domain layer to provide actual data access or external service integration.
    • API Layer: Defines the interfaces, DTOs, and responses for HTTP/RPC.
  6. Understand the role of JPA and Hibernate in Java Persistence

    JPA (Java Persistence API) is a specification that defines interfaces and metadata for object-relational mapping. Hibernate is a full implementation of the JPA specification that also provides its own native API for non-standard features. ORM tools like Hibernate solve several JDBC limitations, including:

    • Verbose API for simple tasks.
    • Lack of transparency for batch operations.
    • Lack of built-in support for explicit locking and optimistic concurrency.
    • Entanglement of data access and transaction management.
    • Complexity in converting ResultSets into domain model/DTO graphs.
  7. Coordinate distributed transactions using JTA and 2PC

    The Java Transaction API (JTA) supports distributed transactions across multiple heterogeneous resource managers (e.g., multiple DataSources or JMS queues) using the X/Open XA architecture. It employs a Two-Phase Commit (2PC) protocol:

    1. Prepare Phase: The transaction manager asks all resource managers to prepare for commit. If any resource manager fails to confirm, the entire transaction is rolled back.
    2. Commit Phase: If all managers confirm the prepare phase, the transaction manager instructs all participants to commit.

    Optimization (1PC): When a transaction involves only a single resource manager, the prepare phase can be skipped (One-Phase Commit) to reduce network overhead. This is triggered by setting the onePhase flag to true in XAResource.commit(Xid xid, boolean onePhase).

  8. Understand database durability and recovery mechanisms

    Durability ensures that all committed transaction changes are permanent and recoverable even after a system crash. This is achieved through two primary logging mechanisms:

    • Undo Log: Used to support transaction rollbacks and reconstruct previous versions of data in MVCC systems. It is not sufficient for full recovery as old segments are frequently recycled.
    • Redo Log: An append-only sequential data structure where all changes are persisted after a transaction commits, ensuring the system can recover committed data after a crash.
  9. Handle JDBC ResultSet concurrency and persistence

    JDBC provides options for result set updatability and persistence (holdability) across transactions.

    Updatability: Updatable result sets allow modifying records while iterating. However, for Web applications, they are generally discouraged because keeping a result set (and its underlying connection) open across multiple HTTP requests severely limits scalability. Read-only, forward-only cursors typically offer better performance.

    Holdability (Persistence): Determines if a result set remains open after a transaction is committed.

    • Oracle/MySQL: Only support HOLD_CURSORS_OVER_COMMIT.
    • SQL Server: Defaults to keeping result sets open; also supports CLOSE_CURSORS_AT_COMMIT.
    • PostgreSQL: Defaults to CLOSE_CURSORS_AT_COMMIT but supports HOLD_CURSORS_OVER_COMMIT.

    Best Practice: To ensure scalability and release system resources, explicitly close all ResultSet and Statement objects as soon as they are no longer needed, regardless of the holdability setting.

  10. Install and configure fzf.vim with ripgrep

    To enable powerful fuzzy searching in Vim, install the fzf and ripgrep (rg) command-line tools. To ensure fzf uses ripgrep for file listing, define the FZF_DEFAULT_COMMAND environment variable in your shell configuration file (.zshrc or .bashrc).
    # In .zshrc or .bashrc
    if type rg &> /dev/null; then
      export FZF_DEFAULT_COMMAND='rg --files'
      export FZF_DEFAULT_OPTS='-m' # Allows multiple selections with <Tab>/<Shift-Tab>
    fi
  11. Declare and initialize variables in Go

    Variables are declared using the var keyword. Go supports type inference and ensures every variable is initialized to a 'zero value' if no explicit value is provided, preventing uninitialized variable errors.

    Zero Values:

    • Numeric types: 0
    • Boolean: false
    • String: "" (empty string)
    • Interface, Slice, Pointer, Map, Channel, Function: nil
    • Arrays/Structs: Each element/field is set to its respective zero value.
    // General syntax: var name type = expression
    var s string          // Initialized to "" (zero value)
    var i, j, k int       // Multiple variables of the same type
    var b, f, s = true, 2.3, "four" // Type inference from expressions
    
    // Initialize from function returning multiple values
    var f, err = os.Open(name)
  12. Use short variable declarations in Go

    Short variable declarations use the := operator to declare and initialize local variables inside a function. The type is automatically inferred from the expression on the right.

    Key rules:

    1. Scope: Only usable inside functions.
    2. Redeclaration: In a multi-variable short declaration (e.g., a, b := 1, 2), at least one variable on the left side must be new to the current lexical scope. If some variables were already declared in the same scope, they are simply assigned new values.
    3. Difference from Assignment: := is for declaration and initialization; = is for assignment to an existing variable.
    // Single variable
    t := 0.0
    
    // Multiple variables
    i, j := 0, 1
    
    // Using function return values
    f, err := os.Open(name)
    
    // Partial redeclaration: 'out' is new, 'err' is reused
    in, err := os.Open(infile)
    out, err := os.Create(outfile)
    
    // This would cause a compile error: "no new variables"
    f, err := os.Open(infile)
    f, err := os.Create(outfile)