Frank's Technical Interview Guide

website·Indexed 30 days ago

https://frank5337.github.io

A comprehensive collection of technical interview questions and answers covering MySQL (InnoDB, MVCC, indexing, and SQL tuning), Redis (Cluster, Sentinel, RDB/AOF, and cache consistency), Spring Framework (Bean lifecycle, AOP, and Spring Boot starters), Message Queues (Kafka throughput and high availability), and System Design (high-concurrency systems, leaderboards, and notification services).

Tokens
32K
Snippets
45
Records
199
Agent score
75%

What's inside Frank's Interview Guide

  1. Overview of the Java Utility Concurrent (JUC) framework

    The java.util.concurrent (JUC) package is the core toolkit for concurrent programming in Java. Its architecture can be categorized into five primary components:

    1. Locks: Tools for mutual exclusion and read/write synchronization, such as ReentrantLock, ReadWriteLock, and StampedLock.
    2. Atomic Classes: Classes for lock-free atomic operations, such as AtomicInteger, AtomicReference, and LongAdder.
    3. Concurrent Collections: Thread-safe data structures, such as ConcurrentHashMap and BlockingQueue.
    4. Thread Pools: Frameworks for managing worker threads and asynchronous tasks, such as ThreadPoolExecutor and CompletableFuture.
    5. Synchronization Utilities: Coordination tools for thread synchronization, such as CountDownLatch, Semaphore, and CyclicBarrier.
  2. Overview of the Java Concurrent (JUC) Framework Architecture

    The java.util.concurrent (JUC) package is a comprehensive toolkit for concurrent programming in Java, categorized into five main components:

    1. Lock Mechanisms: Includes ReentrantLock (reentrant mutual exclusion), ReentrantReadWriteLock (shared read/exclusive write), StampedLock (optimistic reading), Condition (replaces wait/notify), and LockSupport (thread blocking via park/unpark).
    2. Atomic Classes: Provides lock-free atomic operations for primitives (AtomicInteger, AtomicLong, AtomicBoolean), references (AtomicReference), versioned references to solve ABA problems (AtomicStampedReference), high-concurrency accumulators (LongAdder, LongAccumulator), and arrays (AtomicIntegerArray).
    3. Concurrent Collections: Thread-safe data structures including ConcurrentHashMap, CopyOnWriteArrayList, ConcurrentLinkedQueue, and various BlockingQueue implementations (ArrayBlockingQueue, LinkedBlockingQueue, PriorityBlockingQueue, SynchronousQueue, DelayQueue).
    4. Executor Framework: Thread pool management including ThreadPoolExecutor, ScheduledThreadPoolExecutor, ForkJoinPool, the Executors factory, and asynchronous result handling via Future and CompletableFuture.
    5. Synchronization Utilities: Coordination tools such as CountDownLatch (one-time countdown), CyclicBarrier (reusable barrier), Semaphore (concurrency limit), Phaser (phased synchronization), and Exchanger (data exchange between threads).
  3. Design a URL Shortening System (TinyURL)

    A URL shortening system requires a design that handles the mapping between long URLs and short codes, ensuring high availability for redirections and protection against abuse. The core components of the design include:

    1. Short Code Generation: Creating a unique, short identifier for each URL.
    2. Mapping Storage: Storing the relationship between the short code and the original long URL.
    3. High-Availability Redirection: Ensuring the system can quickly redirect users from the short URL to the long URL with minimal latency.
    4. Anti-Abuse and Statistics: Implementing mechanisms to prevent spam/brushing and track usage metrics.
  4. Understand the MySQL Master-Slave Replication Process

    MySQL master-slave replication follows a specific data pipeline to synchronize data from the primary (master) server to the replica (slave) server:

    1. Master Server: Writes changes to the binary log (binlog).
    2. Slave IO Thread: Connects to the master, pulls the binlog events, and writes them to the local relay log (relay log).
    3. Slave SQL Thread: Reads the relay log and replays the operations on the slave database to achieve consistency.

    Key characteristics include:

    • Asynchronous by Default: The master does not wait for the slave to confirm receipt of the logs before committing a transaction.
    • Replication Lag: Because the process is asynchronous, there is a time gap between a write on the master and its appearance on the slave.
  5. Understand ThreadLocal internal mechanism and thread isolation

    ThreadLocal achieves thread isolation by maintaining a ThreadLocalMap inside each individual thread. In this map, the ThreadLocal instance serves as the key, and the business data serves as the value. This ensures that each thread has its own independent copy of the variable.
  6. Understand the core principle of Spring Boot Starters

    A Spring Boot Starter is essentially a combination of 'a set of dependencies' and 'a set of auto-configurations'. It bundles the necessary libraries and default assembly logic required for a specific capability, allowing a business project to enable that functionality quickly by simply importing the starter dependency. The implementation typically relies on Spring Boot's auto-configuration mechanism and conditional annotations.
  7. Architectural design of a user notification system

    A robust user notification system should be designed using a layered architecture to separate concerns between request ingestion, content formatting, and delivery. The recommended layers are:

    1. Access Layer (接入层): Handles incoming notification requests.
    2. Template Layer (模板层): Manages message templates to decouple content from logic.
    3. Routing/Dispatch Layer (路由分发层): Determines which channels and users should receive the notification.
    4. Multi-channel Delivery Layer (多渠道发送层): Integrates with various delivery providers (e.g., SMS, Email, Push).
    5. Status Receipt Layer (状态回执层): Tracks delivery status and handles callbacks from providers.

    To ensure system reliability, the following capabilities must be implemented:

    • Idempotency: Prevent duplicate notifications for the same event.
    • Retry Mechanism: Handle transient failures in delivery channels.
    • Rate Limiting: Protect downstream providers and prevent spamming users.
    • Auditing: Maintain logs for compliance and troubleshooting.
  8. How Spring Boot auto-configuration works

    Spring Boot auto-configuration follows a three-step process during application startup:

    1. Loading: The application loads candidate auto-configuration classes (triggered by @EnableAutoConfiguration).
    2. Conditional Evaluation: The framework uses @Conditional annotations to determine if a configuration should be applied based on the environment or classpath.
    3. Injection: If the conditions are met, the corresponding default Beans are injected into the Spring application context.

    Commonly used conditional annotations include:

    • @ConditionalOnClass: The configuration is enabled only if a specific class is present on the classpath.
    • @ConditionalOnMissingBean: The configuration is enabled only if a bean of a specific type has not already been defined.
    • @ConditionalOnProperty: The configuration is enabled based on the presence or value of a specific configuration property.
  9. Understand the Compare-And-Swap (CAS) mechanism

    CAS (Compare-And-Swap) is a lock-free mechanism used in Java's Atomic classes. It is implemented as a CPU instruction (e.g., lock cmpxchg) that compares the current memory value with an expected value; if they match, the value is updated to a new one. This ensures atomicity without using traditional locks. If the CAS operation fails (because the value changed), the thread typically enters a loop (spin) to retry the operation.
    // Conceptual logic of AtomicInteger.incrementAndGet()
    do {
        int expected = get();        // Read current value
        int newValue = expected + 1; // Calculate new value
    } while (!compareAndSet(expected, newValue));  // Retry if CAS fails
  10. Understand data consistency in Redis Cluster

    Redis Cluster ensures data consistency primarily through master-slave replication. Because this replication is asynchronous by default, Redis provides eventual consistency rather than strong consistency. Developers should be aware of two critical constraints:

    1. Data loss can occur during master-slave failover (switching) because some data may not have been synchronized to the slave yet.
    2. Redis is not suitable for scenarios requiring strong transactional consistency (e.g., financial ledgering).

    In practical architectures, Redis should be used as a high-speed access layer for data like inventory or sessions, while the system of record (e.g., a relational database) must remain the authoritative source for final settlements and financial transactions to mitigate the risk of data loss during failovers.

  11. Compare JDK Dynamic Proxy and CGLIB

    JDK Dynamic Proxy and CGLIB are the two primary mechanisms used for proxying objects in Java and Spring. The fundamental difference lies in their implementation strategy: JDK Dynamic Proxy relies on interfaces, while CGLIB relies on class inheritance to create a subclass of the target object. In practice, if the target class implements at least one interface, JDK Dynamic Proxy is typically preferred; otherwise, CGLIB is used as a fallback.
  12. Understand common JVM Garbage Collection (GC) processes

    JVM utilizes different types of GC processes depending on the memory area being reclaimed:

    • Young GC / Minor GC: Primarily reclaims the Young Generation. It occurs frequently and typically has short pause times.
    • Mixed GC: Specific to the G1 collector; it reclaims both the Young Generation and parts of the Old Generation simultaneously.
    • Full GC: Reclaims the entire heap and the Metaspace. This process usually results in longer application pauses.