Chia sẻ kiến thức IT và đời sống – Sharing IT Knowledge and Life

Thứ Bảy, 31 tháng 10, 2026

Redis A–Z, Java & TTL: Overview

A concise guide to Redis: what it is, how to deploy it, how it persists data, when you need it, how to use it in Java, and how TTL works. Every code block is labeled as one of the following types: a Redis command, Java code, or a configuration file.

Vietnamese version 

Redis at a glance

Redis is a fast in-memory data store commonly used alongside a primary database such as PostgreSQL or MySQL. In Java/Spring applications, its most common jobs are caching, shared sessions, distributed coordination, rate limiting, and real-time counters.

Highlights

  • What Redis is and how its deployment models differ.
  • How RDB and AOF protect data when Redis restarts.
  • When Redis is useful, and when a normal database is enough.
  • How Java/Spring code maps to Redis commands.
  • How TTL, expiration, and eviction work in practice.

Suggested reading order: read sections 1–4 first to understand Redis; then choose the Java use case in section 5 that matches your application; finally read section 6 to understand expiration and memory management.

How to read this article

Redis articles mix several "languages" in one page, which is confusing at first. Here is how each block is labeled:

LabelWhat it isWhere you use it
REDIS COMMANDA command you type directly into Redis (like SQL for a SQL database). Dark background.Terminal, running redis-cli
JAVA CODEJava (Spring Boot) code that talks to Redis. Light background.Your application source code
CONFIG / XMLSettings files, not code that runs by itself.redis.conf, application.properties, pom.xml
LUA SCRIPTA small script that runs inside Redis, so several steps execute as one unit.Sent to Redis with the EVAL command

Small things that look strange but are simple:

  • Redis blocks: the > at the start of a line is the redis-cli prompt. You type what comes after it. Lines without > are Redis's reply (for example (integer) 1 means "the answer is the number 1", and (nil) means "nothing / not found").
  • Command names are case-insensitive (set = SET), but by convention they are written in UPPERCASE so they stand out from keys and values.
  • key and value in a command pattern are placeholders. You replace them with your own names.
  • Colons in key names such as rate:user42 or lock:product:7 are only a naming habit to group keys (like folders). Redis does not treat : as special.
  • ... inside a sentence means "and other options / and others". It is not part of the syntax.
  • // in Java code starts a comment. Redis config files use # for comments.
  • Unknown word? Jump to the Glossary (section 8).

1. What is Redis?

Redis (Remote Dictionary Server) is a NoSQL key-value database that keeps data mainly in RAM, so reads and writes are extremely fast (sub-millisecond, meaning less than 1/1000 of a second).

  • It is a real database: you can insert, update, delete, and query data like any other DB. The difference is that you use commands (SET, GET, HSET, ZADD...) instead of SQL.
  • Data types: String, Hash, List, Set, Sorted Set, Stream, Bitmap, HyperLogLog, Geo.
  • Built-in persistence, replication, transactions, pub/sub, and TTL.

A first taste. SET stores a value under a key, GET reads it back:

REDIS COMMAND · type in redis-cli
> SET user:1:name "Linh"
OK
> GET user:1:name
"Linh"
> GET user:999:name
(nil)

The last reply is (nil) because that key does not exist.

2. Deployment Models

ModelDescriptionWhen to use
StandaloneA single instanceSmall/medium apps that tolerate short downtime
Master-ReplicaOne master for writes, replicas (read-only copies) for readsNeed more read capacity and a backup copy
SentinelMaster-Replica plus monitoring and automatic failover (if the master dies, a replica is promoted to master automatically)Need high availability (HA), meaning the system stays up when one server fails; data fits on one machine
ClusterData is sharded (split into pieces) across 16,384 hash slots, each shard with replicasData exceeds one machine's RAM; need to scale reads and writes
Rule of thumb: start with Standalone, move to Sentinel for HA, and use Cluster when you need to scale data or writes.

3. Persistence: RDB vs AOF

Persistence means saving RAM data to disk, so it survives a restart.

RDB (snapshot) takes periodic point-in-time dumps of the whole dataset.

  • Pros: compact file, fast restore, low performance impact.
  • Cons: a crash loses everything since the last snapshot.

AOF (Append Only File) logs every write command.

  • Pros: much more durable. With appendfsync everysec you lose at most ~1 second of data.
  • Cons: larger files and slower restore (mitigated by AOF rewrite, which compacts the log).

Why AOF if we already have RDB? RDB is only a periodic snapshot, so a crash between two snapshots loses data. AOF records continuously and minimizes that loss.

What should you choose?

  • Pure cache: disable persistence, or use RDB only.
  • Important data: enable RDB + AOF (everysec). RDB gives fast backups and restores, AOF gives durability. On restart, Redis prefers the AOF because it is more complete.

Note that appendfsync everysec is not a command you type. It is a setting in the Redis config file:

CONFIG · redis.conf
# RDB: take a snapshot if at least 1 key changed within 900 seconds
save 900 1

# AOF: turn it on, and flush the log to disk once per second
appendonly yes
appendfsync everysec

fsync means "force the data to be physically written to disk". everysec = do it every second (a good balance of safety and speed).

4. When Do You Actually Need Redis?

Not every application needs Redis. Adding it means more infrastructure, more operational cost, and the risk of cache inconsistency (the cache and the database showing different data).

Use Redis when:

  • The workload is read-heavy and the main DB is overloaded (caching: keeping a fast copy of frequently read data).
  • You need very fast responses: leaderboards, view counters, rate limiting (limiting how many requests a user may make).
  • Multiple app servers must share sessions (the "this user is logged in" information).
  • You need distributed locks (a lock shared across several servers), lightweight queues, or pub/sub (publish/subscribe messaging).
  • You store short-lived data: OTPs (One-Time Passwords, such as the 6-digit code sent by SMS) and tokens (temporary proof of identity, such as a password-reset link code).

You probably don't need it when:

  • It is an internal app with few users and the DB handles the load fine.
  • You haven't optimized your indexes and queries yet. Do that first.
  • You need strict ACID guarantees (reliable transactions) and complex relations. Redis does not replace an RDBMS (relational database such as MySQL or PostgreSQL).
  • Budget or ops skills are limited: RAM costs more than disk, and Sentinel/Cluster need someone who can run them.
Scale hint: consider Redis when DB latency (response time) starts rising, repeated reads reach thousands of requests per second, or multiple app instances need shared state.

5. Redis in Java

Common clients (Java libraries that connect to Redis):

  • Spring Data Redis (RedisTemplate, StringRedisTemplate): the most popular choice in Spring Boot.
  • Lettuce (Spring Boot default, async/non-blocking) and Jedis (simple, synchronous).
  • Redisson: ready-made distributed locks, semaphores, rate limiters, and collections.

The key idea: Java methods are just translated into Redis commands

When your Java code calls redisTemplate.opsForValue().increment(key), the library sends the Redis command INCR key to the server. Same thing, different "language". Keep this table handy, because the rest of the article uses both forms:

Java code (RedisTemplate)Redis command it sendsMeaning
opsForValue().set(k, v)SET k vStore a value
opsForValue().set(k, v, 60, TimeUnit.SECONDS)SET k v EX 60Store a value that expires in 60 s
opsForValue().get(k)GET kRead a value
opsForValue().increment(k)INCR kAdd 1 to a number
expire(k, 1, TimeUnit.MINUTES)EXPIRE k 60Set a lifespan on an existing key
opsForZSet().incrementScore(k, m, 50)ZINCRBY k 50 mAdd 50 points to member m
opsForZSet().reverseRangeWithScores(k, 0, 9)ZREVRANGE k 0 9 WITHSCORESTop 10, highest first
opsForZSet().reverseRank(k, m)ZREVRANK k mRank of member m

5.1 Caching with @Cacheable

Idea: before running an expensive database query, check Redis first. If the answer is there (a cache hit), return it. If not (a cache miss), query the DB and store the result in Redis for next time.

In Spring you do this with annotations. An annotation is a label starting with @ that you put above a method to add behavior without writing the logic yourself.

JAVA CODE · Spring Boot
@Cacheable(value = "products", key = "#id")   // return cached value, or run method and store it
public Product getProduct(Long id) { return repo.findById(id).orElseThrow(); }

@CachePut(value = "products", key = "#p.id")  // always run and update the cache
public Product update(Product p) { return repo.save(p); }

@CacheEvict(value = "products", key = "#id")  // remove from cache when data changes
public void delete(Long id) { repo.deleteById(id); }

Reading the annotation parameters:

  • value = "products": the name of the cache (think of it as a folder name).
  • key = "#id": the cache key. #id is a Spring expression (SpEL) meaning "use this method's parameter called id". #p.id means "the id field of parameter p".
  • In Redis, the entry ends up under a key like products::5 (cache name + :: + key). You can inspect it with a Redis command:
REDIS COMMAND · type in redis-cli
> KEYS products::*
1) "products::5"
> TTL products::5
(integer) 540

KEYS pattern lists keys matching a pattern (* = anything). Use it only for debugging on a small dev instance, because it is slow on big databases.

Notes:

  • When DB data changes, you must @CacheEvict or @CachePut, or readers will see stale (outdated) data.
  • Caching works through a proxy (Spring wraps your class with a helper object), so calling a method from within the same class bypasses the cache.
  • To prevent cache penetration (repeated queries for keys that don't exist, which always fall through to the DB), cache null values with a short TTL.

5.2 Sessions with Spring Session

Problem: behind a load balancer (a device that spreads requests across several servers), in-memory sessions are tied to one server, so users get logged out when a request lands on another.
Solution: store sessions centrally in Redis.

Step 1: add the library to your Maven build file.

XML · pom.xml (Maven)
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

Step 2: tell Spring where Redis is.

CONFIG · application.properties
spring.data.redis.host=localhost
spring.data.redis.port=6379

(On Spring Boot 2.x the prefix is spring.redis.* instead of spring.data.redis.*.)

That's all. Spring Boot swaps HttpSession for a Redis-backed one. Your session.setAttribute(...) code stays the same. Stored objects must be serializable (convertible to bytes so they can be saved). Sessions appear in Redis as keys starting with spring:session:, with a TTL equal to the session timeout. If you use stateless JWT (a signed token the client carries, so the server stores nothing), you usually don't need this.

5.3 Distributed Locks with Redisson

Problem: Java's synchronized only locks within a single JVM (one running Java program). Across multiple instances, two requests can still process the same resource at once (e.g., both decrementing the same stock).

Idea: use a key in Redis as the lock. Whoever creates the key first owns the lock. Under the hood, the simplest version is this Redis command:

REDIS COMMAND · type in redis-cli
> SET lock:product:7 server-A NX PX 10000
OK
> SET lock:product:7 server-B NX PX 10000
(nil)
  • NX = "only set if the key does Not eXist". The first caller gets OK (lock acquired). The second gets (nil) (lock already taken).
  • PX 10000 = expire after 10,000 milliseconds (10 s), so a crashed server cannot hold the lock forever.
  • server-A is the owner id, so only the owner releases it.

Writing this safely by hand is tricky, so the Java library Redisson does it for you:

JAVA CODE · Redisson
RLock lock = redisson.getLock("lock:product:" + productId);
try {
    // wait up to 5s to acquire, auto-release after 10s
    if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
        // decrement stock, create order...
    } else {
        throw new RuntimeException("System busy, try again later");
    }
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
} finally {
    if (lock.isHeldByCurrentThread()) lock.unlock();
}
  • tryLock(5, 10, SECONDS): wait up to 5 s for someone else to release; once you get it, it auto-expires after 10 s (the "lease time").
  • finally { ... }: this block always runs, even after an error, so the lock is always released.
  • isHeldByCurrentThread(): only unlock if you still own it (it may have already expired).
  • InterruptedException handling: standard Java housekeeping when a waiting thread is interrupted.

Why Redisson over a hand-rolled SET NX: it has a watchdog (a background task, which by default renews the lock every ~10 s with a 30 s lease) that extends the lock while work is still running (only when you do not pass a lease time), and it supports reentrancy (the same thread can lock twice), fair locks, read-write locks, and semaphores.

Notes: always set an expiry to avoid deadlocks if a server dies, and only unlock a lock you hold. For critical business rules, add a DB-level safeguard (unique constraint or optimistic locking) as the last line of defense.

5.4 Rate Limiting

Rate limiting = restricting how many requests one user may send in a period of time, e.g. "max 100 requests per minute". It protects your API from abuse and overload.

What does "window" mean?

The window is simply the length of time over which you count. For "100 requests per minute", the window is 1 minute. A fixed window means the time is cut into fixed blocks (12:00:00–12:00:59, then 12:01:00–12:01:59, ...) and the counter starts again from 0 at each new block.

The Redis commands behind it

The limiter uses two commands: INCR (add 1 to a counter; creates it at 1 if missing) and EXPIRE (delete the key automatically after N seconds). Here is one user's first requests:

REDIS COMMAND · type in redis-cli
> INCR rate:user42
(integer) 1
> EXPIRE rate:user42 60
(integer) 1
> INCR rate:user42
(integer) 2
> TTL rate:user42
(integer) 52
  1. First request: counter becomes 1. Because it is the first, we also start the 60-second window with EXPIRE.
  2. Next requests: counter goes 2, 3, 4... (we do not call EXPIRE again, or the window would keep sliding forward).
  3. After 60 seconds the key disappears, so the next INCR starts again at 1: a new window.
  4. If the counter goes above 100, we reject the request.

The same logic in Java

JAVA CODE · Spring Data Redis
public boolean allow(String userId) {
    String key = "rate:" + userId;                              // e.g. "rate:user42"
    Long count = redisTemplate.opsForValue().increment(key);    // = INCR rate:user42
    if (count == 1) {                                           // first request of this window
        redisTemplate.expire(key, 1, TimeUnit.MINUTES);         // = EXPIRE rate:user42 60
    }
    return count <= 100;   // true = allowed, false = over the limit (max 100 requests/minute)
}

If it returns false, respond with HTTP 429 Too Many Requests (the standard status code meaning "slow down").

Notes:

  • Burst at the boundary. A fixed window resets abruptly. A user can send 100 requests at 12:00:59 and another 100 at 12:01:00, which is 200 requests in 2 seconds while still "within the limit". For smoother behavior use a Sliding Window (the window moves with time; implemented with a Sorted Set) or a Token Bucket (you spend tokens that refill at a steady rate).
  • Not atomic. INCR and EXPIRE are two separate commands. If the app crashes between them, the key never expires and the user is blocked forever. Atomic means "all steps happen as one indivisible unit". The fix is to combine them in a Lua script, which Redis runs without interruption:
LUA SCRIPT · runs inside Redis
local count = redis.call('INCR', KEYS[1])
if count == 1 then
  redis.call('EXPIRE', KEYS[1], ARGV[1])
end
return count

Run it with the EVAL command. KEYS[1] and ARGV[1] are the values you pass in (the key name, and the window length in seconds):

REDIS COMMAND · type in redis-cli
> EVAL "local c = redis.call('INCR', KEYS[1]) if c == 1 then redis.call('EXPIRE', KEYS[1], ARGV[1]) end return c" 1 rate:user42 60
(integer) 1

Here 1 after the script means "I am passing 1 key", then come the key (rate:user42) and the extra argument (60).

  • Redisson offers RRateLimiter out of the box, so you write no counting logic yourself:
JAVA CODE · Redisson
RRateLimiter limiter = redisson.getRateLimiter("api:" + userId);
limiter.trySetRate(RateType.OVERALL, 100, 1, RateIntervalUnit.MINUTES);  // 100 permits per 1 minute
if (limiter.tryAcquire(1)) { /* allowed: we took 1 permit */ }

RateType.OVERALL means the limit is shared by all clients using this limiter (PER_CLIENT would give each client its own limit). A "permit" is one allowed request.

5.5 Leaderboards with Sorted Sets

A Sorted Set (ZSET) is a collection where every member has a score, and Redis keeps the members ordered by score automatically. Adding, updating, and fetching the top N are all O(log N). In plain words: even with 1,000,000 members, Redis needs only about 20 steps, far cheaper than running ORDER BY score DESC on a large SQL table.

All Sorted Set commands start with the letter Z (that is how you recognize them). REV in a name means "reverse order" (highest first).

Redis commandPurpose
ZADD / ZINCRBYAdd a member (with a score), or increment its score (INCR + BY)
ZREVRANGEGet the top N (highest first). Range = positions, so 0 9 means the 1st to the 10th
ZREVRANKGet a member's rank (0 = first place)
ZSCOREGet a member's score

Redis commands in action:

REDIS COMMAND · type in redis-cli
> ZINCRBY leaderboard:game1 50 alice
"50"
> ZINCRBY leaderboard:game1 80 bob
"80"
> ZREVRANGE leaderboard:game1 0 9 WITHSCORES
1) "bob"
2) "80"
3) "alice"
4) "50"
> ZREVRANK leaderboard:game1 alice
(integer) 1
> ZSCORE leaderboard:game1 bob
"80"

The same thing from Java (compare with the translation table above):

JAVA CODE · Spring Data Redis
redis.opsForZSet().incrementScore("leaderboard:game1", userId, points);  // add points
redis.opsForZSet().reverseRangeWithScores("leaderboard:game1", 0, 9);    // top 10
redis.opsForZSet().reverseRank("leaderboard:game1", userId);             // rank (0-based)

For daily or weekly boards, put the date in the key (leaderboard:2026-10-31) and attach a TTL (e.g. EXPIRE leaderboard:2026-10-31 604800 = delete after 7 days). Ties: members with equal scores are ordered alphabetically by name. To favor "who reached the score first", encode the timestamp in the score's decimal part (earlier time = slightly larger decimal), so the earlier player ranks higher.

6. TTL: Time To Live

TTL is a key's lifespan. When it runs out, Redis deletes the key automatically. It is the main tool that keeps a cache from growing forever and stale data from living indefinitely.

6.1 Common commands

Redis commandMeaning
SET key value EX 300Set a value with a TTL of 300 seconds. EX = seconds; PX = milliseconds (1000 ms = 1 s)
EXPIRE key 60 / PEXPIRE key 1500Set a TTL on an existing key (seconds / milliseconds)
TTL key / PTTL keyShow remaining time (seconds / milliseconds)
PERSIST keyRemove the TTL so the key lives forever

Tip: a leading P in a Redis command always means milliseconds (PEXPIRE, PTTL, and the PX option).

TTL returns -1 if the key exists but has no expiry, and -2 if the key does not exist (it never existed, or it already expired).

REDIS COMMAND · example: a 5-minute OTP
> SET otp:user42 123456 EX 300
OK
> TTL otp:user42
(integer) 297
> GET otp:user42
"123456"

(5 minutes later)
> GET otp:user42
(nil)
> TTL otp:user42
(integer) -2

6.2 Common pitfalls

  • A plain SET on an existing key clears its TTL. Use SET ... KEEPTTL to keep it (here ... stands for your key and value).
  • Reading a key (GET) does not refresh its TTL. For sliding expiration (the lifespan restarts every time the key is used, as with sessions), call EXPIRE again or use GETEX (read and set a new TTL in one command).
  • TTL applies to the whole key, not to individual elements inside a Hash, List, or Set.
REDIS COMMAND · pitfalls in action
> SET session:1 abc EX 1800
OK
> SET session:1 xyz
OK
> TTL session:1
(integer) -1

> SET session:1 xyz KEEPTTL
OK
> GETEX session:1 EX 1800
"xyz"

After the second SET, the TTL is -1 (the expiry was wiped). GETEX session:1 EX 1800 returns the value and restarts the 30-minute lifespan.

6.3 How Redis removes expired keys

  • Lazy: when a key is accessed, Redis checks it and deletes it if expired.
  • Active: periodically, Redis samples (randomly checks) keys that have a TTL and deletes the expired ones.

So an expired key may not free memory immediately, but you will never be able to read it. With replicas, the master decides expiration and sends a DEL (delete) command to replicas (and writes it to the AOF).

6.4 TTL vs eviction when RAM is full

Eviction means Redis deleting keys on its own because memory is full. It is different from TTL (deleting because time ran out). When memory hits maxmemory, Redis follows maxmemory-policy. Both are settings in redis.conf, not commands:

CONFIG · redis.conf
maxmemory 2gb                    # the RAM limit
maxmemory-policy allkeys-lru     # what to delete when the limit is reached
  • noeviction (default): rejects new writes with an error.
  • allkeys-lru: evicts the Least Recently Used keys (the ones not touched for the longest time) across everything. Good for pure caches.
  • volatile-lru / volatile-ttl: evicts only among keys that have a TTL ("volatile" = has an expiry). Good when cache and must-keep data share one instance.

6.5 Choosing a TTL

Data typeSuggested TTLWhy
OTP / verification codes (One-Time Password: the 6-digit code sent by SMS/email)1 to 5 minutesA code that lives too long is a security risk
Rate-limit countersExactly the window length (1 second, 1 minute...)The window is the period you count in (see 5.4). TTL = window length makes the counter reset exactly when a new window starts. Too short lets users exceed the limit; too long blocks them longer than intended
Sessions15 to 30 minutes, renewed on activityLogs out idle users, but active users stay logged in
Rarely changing cache (categories, config)A few hours to 1 dayData rarely changes, so a long TTL saves many DB reads
Frequently changing cache (price, stock)A few seconds to a few minutesWrong data is costly, so keep it fresh
Cached nulls (anti-penetration)30 seconds to 2 minutesShort, because the record may be created soon

Longer TTL saves more DB load but makes data staler. Pick based on how much staleness the business can tolerate.

6.6 Cache avalanche: avoid simultaneous expiry

If many keys are loaded together with the same TTL, they expire together and all requests hit the DB at once (a cache avalanche). Fix it by adding a random extra time, called jitter, to each TTL:

JAVA CODE · Spring Data Redis
long ttl = 600 + ThreadLocalRandom.current().nextInt(0, 120); // 10 min + 0~2 min
redisTemplate.opsForValue().set(key, value, ttl, TimeUnit.SECONDS);  // = SET key value EX ttl

ThreadLocalRandom is Java's random-number generator. nextInt(0, 120) gives a random whole number from 0 to 119, so each key lives between 600 and 719 seconds and they no longer expire at the same moment.

6.7 Per-cache TTL in Spring

Different caches often need different TTLs. In Spring you define them once in a configuration class (@Bean marks a method whose result Spring manages for you):

JAVA CODE · Spring Boot configuration
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory cf) {
    RedisCacheConfiguration base = RedisCacheConfiguration.defaultCacheConfig()
        .entryTtl(Duration.ofMinutes(10));                 // default TTL: 10 minutes

    return RedisCacheManager.builder(cf)
        .cacheDefaults(base)
        .withCacheConfiguration("categories", base.entryTtl(Duration.ofHours(6)))    // this cache: 6 hours
        .withCacheConfiguration("stock",      base.entryTtl(Duration.ofSeconds(30))) // this cache: 30 seconds
        .build();
}

The names "categories" and "stock" are the same cache names you put in @Cacheable(value = "...") (see 5.1). Duration.ofMinutes(10) is just Java's way of writing "10 minutes".

7. Summary

TopicKey takeaway
What it isIn-memory NoSQL key-value database, operated by commands instead of SQL
DeploymentStandalone, then Sentinel (HA), then Cluster (scale data)
PersistenceRDB for fast backup/restore, AOF for durability; use both for important data
When neededDB overloaded by repeated reads, real-time speed, or shared state across instances
CacheJava: @Cacheable, and remember @CacheEvict when data changes
SessionSpring Session shares logins across servers
LockJava: Redisson RLock (Redis idea: SET ... NX PX), always with an expiry
Rate limitRedis: INCR + EXPIRE (or a Lua script); Java: Redisson RRateLimiter
LeaderboardSorted Set (ZINCRBY, ZREVRANGE), O(log N)
TTLAlways set it for caches, add jitter, choose by acceptable staleness

8. Glossary: every unfamiliar term in one place

The "Type" column tells you what kind of thing each term is.

TermTypeMeaning
SET / GETRedis commandStore / read a String value under a key
INCRRedis commandAdd 1 to a numeric key (creates it at 1 if missing). Used for counters
EXPIRE / PEXPIRERedis commandGive an existing key a lifespan, in seconds / milliseconds
TTL / PTTLRedis commandShow remaining lifespan (seconds / milliseconds). -1 = no expiry, -2 = key missing
PERSISTRedis commandRemove a key's lifespan
GETEXRedis commandRead a value and set a new TTL at the same time
DELRedis commandDelete a key
KEYS patternRedis commandList keys matching a pattern. Debugging only, slow on big data
EVALRedis commandRun a Lua script inside Redis
ZADD, ZINCRBY, ZREVRANGE, ZREVRANK, ZSCORERedis commandsSorted Set commands (all start with Z): add, add to score, top N, rank, read score. REV = highest first
HSETRedis commandSet a field inside a Hash (a key that holds several name/value pairs, like a small object)
EX / PXCommand optionUsed with SET: lifespan in seconds (EX) or milliseconds (PX)
NXCommand optionWith SET: only write if the key does Not eXist (used for locks)
KEEPTTLCommand optionWith SET: keep the old TTL instead of wiping it
WITHSCORESCommand optionAlso return each member's score, not just the names
appendfsync everysec, appendonly, saveConfig settingPersistence settings in redis.conf (AOF on/off, flush frequency, RDB snapshot rule)
maxmemory, maxmemory-policyConfig settingRAM limit, and what to delete when it is reached
@Cacheable, @CachePut, @CacheEvictJava annotationSpring labels: use cache / always update cache / remove from cache
@BeanJava annotationMarks a method whose result Spring creates and manages
#idSpring expression"The method parameter named id"
RedisTemplateJava classSpring's main tool for sending commands to Redis; opsForValue() = String commands, opsForZSet() = Sorted Set commands
RLock, RRateLimiterJava class (Redisson)Ready-made distributed lock / rate limiter
KEYS[1], ARGV[1]LuaInside a Lua script: the 1st key and the 1st extra argument you passed to EVAL
WindowConceptThe period of time over which requests are counted (e.g. 1 minute for "100 per minute")
Fixed window / Sliding window / Token bucketConceptThree ways to rate-limit: count in fixed blocks of time / count over a moving period / spend tokens that refill steadily
OTPConceptOne-Time Password: a short-lived code (e.g. 6 digits by SMS) used once
AtomicConceptSeveral steps executed as one indivisible unit; nothing can happen in between
Lua scriptConceptA small script that runs inside Redis, which makes multi-step logic atomic
O(log N)ConceptSpeed notation: when data grows a lot, the time grows only slightly (1 million items = about 20 steps)
TTLConceptTime To Live: how long a key lives before Redis deletes it
Eviction / LRUConceptRedis deleting keys because RAM is full / choosing the least recently used ones
JitterConceptA random extra amount added to TTLs so keys don't all expire together
Cache hit / missConceptThe data was found in the cache / not found, so the DB had to be queried
Cache avalancheConceptMany keys expire at the same moment and all requests hit the DB at once
Cache penetrationConceptRepeated requests for keys that don't exist, which always reach the DB
Stale dataConceptOutdated data (cache still shows the old value after the DB changed)
HA / failoverConceptHigh availability (stays up when a server fails) / automatic switch to a backup server
Shard / hash slotConceptA piece of the data split across servers in Cluster mode; Redis has 16,384 slots that are distributed among shards
SerializableConceptCan be converted to bytes so it can be stored or sent over a network
HTTP 429ConceptStandard "Too Many Requests" response code

Conclusion

Redis shines in speed and its variety of data structures. It usually acts as a cache and real-time layer next to your primary database rather than replacing it. Choose the deployment model based on availability needs and data size, combine RDB + AOF when durability matters, and always set a sensible TTL so your cache stays lean, data stays reasonably fresh, and your system doesn't collapse from an avalanche.

Most importantly: use Redis only when you have a real performance or distributed-architecture problem to solve, because it always comes with infrastructure cost and operational complexity.

Redis A–Z, Java & TTL: Tổng quan

Hướng dẫn ngắn gọn về Redis: Redis là gì, cách triển khai, cách lưu dữ liệu bền vững, khi nào thực sự cần dùng, cách dùng trong Java và cơ chế TTL hoạt động ra sao. Mọi khối mã đều có nhãn là một trong những loại lệnh Redis, mã Java hay file cấu hình.

English version

Chủ Nhật, 18 tháng 10, 2026

MongoDB hay PostgreSQL: dự báo đến 2036

Tiếng Anh

Cuộc tranh luận 'MongoDB hay PostgreSQL' chưa bao giờ hạ nhiệt mỗi khi một kiến trúc hệ thống mới được khởi động. Tuy ranh giới giữa SQL và NoSQL ngày càng mờ đi nhờ việc hai hệ thống liên tục học hỏi lẫn nhau, việc chọn đúng 'bảo bối' vẫn là bài toán quyết định sự thành bại của doanh nghiệp. Bài viết này sẽ mổ xẻ hiệu năng thực tế của MongoDB, cập nhật các con số kinh doanh mới nhất, dự báo thị trường đến năm 2036 và đặt lên bàn cân so sánh chi tiết với PostgreSQL.

MongoDB vs PostgreSQL: forecast to 2036

Vietnamese

Choosing Between MongoDB and PostgreSQL: Data Modeling, Convergence & 2036 Forecast

The “MongoDB or PostgreSQL” debate never cools down whenever a new system architecture is kicked off. Although the line between SQL and NoSQL keeps blurring as the two systems constantly learn from each other, choosing the right “secret weapon” is still a decision that can make or break a business. This article dissects MongoDB’s real-world performance, updates the latest business figures, forecasts the market through 2036 and puts it side by side with PostgreSQL in a detailed comparison.

1. Quick summary

Seven things to remember

  • MongoDB revenue is still growing strongly. Fiscal-year revenue reached a high level with the customer count passing 70,600. The cloud service MongoDB Atlas remains the main growth driver (around 29%).
  • PostgreSQL is developers’ top choice. It leads the Stack Overflow survey on the most used, most desired and most admired criteria.
  • The two systems are converging in features. PostgreSQL adds JSONB and vectors (pgvector), while MongoDB integrates ACID transactions, Atlas Search and Vector Search.
  • The NoSQL market keeps expanding at an estimated rate of about 15% to 20% per year.
  • General scenario for MongoDB: revenue is projected to reach roughly 9 to 10 billion USD by fiscal year 2036. This is a simulated forecast for reference only, not an official figure published by the company.
  • Java staffing: With MongoDB Atlas, a Java developer with a solid foundation is enough to be confident building the backend. However, running in-depth multi-node sharded clusters yourself requires a dedicated DBA or DevOps team.
  • MVPs for SMEs and low-budget starter projects: Both MongoDB Atlas and PostgreSQL offer free or low-cost tiers to validate ideas. When moving to production, consider hosting costs carefully based on the actual configuration.
    (MVP = Minimum Viable Product).

2. Where MongoDB is strong

MongoDB is a document-oriented NoSQL database. Instead of tables, rows and columns, data is stored as JSON documents (in the BSON binary format) grouped into collections. You can use the self-managed edition (Enterprise Advanced) or the MongoDB Atlas cloud service on AWS, Azure and Google Cloud.

Flexible document model

Documents in the same collection can have different, flexible structures. Teams can easily add new fields or change the structure without running complicated migration scripts. This is why MongoDB is extremely well suited to the MVP stage and to products that need fast development.

Horizontal scaling with built-in sharding

As data volume and traffic grow, MongoDB’s sharding automatically distributes data across multiple servers, letting the system scale out instead of constantly upgrading a single server’s hardware (scale-up) at high cost.

High availability through Replica Sets

Each Replica Set consists of one primary node and secondary nodes that keep copies of the data. When the primary fails, the system automatically elects a secondary to take over, minimizing downtime.

Rich querying and indexing

MongoDB strongly supports filters, projection, the aggregation pipeline, the $lookup operator and many index types (secondary, text, geospatial). The _id field is always indexed by default.

Developer-friendly

The object-shaped data structure fits modern programming thinking perfectly, reducing O/M mapping effort. Tools such as MongoDB Compass and the Atlas platform make operations and monitoring easier for teams.

AI ecosystem and integrated platform

MongoDB Atlas has built-in search, vector search and stream processing, plus newer tools such as Automated Embeddings with Voyage AI and the Atlas Managed MCP Server for AI coding agents. Recent releases have also noticeably improved read, write and ACID transaction performance.

3. Limitations to know

  • Complex relationships: The $lookup operator is not as powerful or well optimized as SQL’s traditional JOIN. Data usually has to be embedded and denormalized, which easily leads to duplication.
  • Technical limits: The maximum size of a single document is 16 MB (larger files need GridFS) and the maximum nesting depth is 100 levels.
  • Storage overhead: Field names are stored in every document and, combined with denormalization, this consumes more disk space and RAM.
  • Multi-document transactions: Although multi-document ACID has been supported since version 4.0, ACID is not the ultimate core strength it is in PostgreSQL. For demanding core financial systems, think carefully.
  • Atlas costs: They tend to rise quickly as data and requests grow, so cost optimization has to be planned early.
  • Community and ecosystem: Smaller than PostgreSQL’s (which dates back to 1996 and has a huge number of extensions).

4. Which scale, industry and application MongoDB fits

By company size

SizeFitReason
Startups, Digital NativesHigh for development speedBuild an MVP quickly, flexible schema, Atlas reduces the initial DevOps burden.
Small and medium businesses, Scale-upsHighSimple operations, easy to scale, but cloud costs need close monitoring.
Large enterprisesHigh (per workload)Usually applied to specific systems (such as large-scale catalog management or customer profiles).
Heavily regulated organizations (Finance, Government)Medium to highUse the Enterprise Advanced package (self-managed or hybrid) to meet high security standards.

By industry & application

  • E-commerce: Managing product catalogs with diverse attributes, shopping carts and customer profiles.
  • Finance, Digital Banking: Storing identity records and large-scale unstructured data.
  • IoT & Time-series: Constantly changing sensor data with an extremely high write rate.
  • Gaming & Social Media: Storing player profiles, item inventories and newsfeeds.

Hosting cost reference for low-budget MVPs

OptionReference costNotable limits
MongoDB Atlas Free (M0)0 USD512 MB, shared resources, no SLA. Suitable for learning and prototyping.
MongoDB Atlas Flex~8 – 30 USD/monthUp to 5 GB, with a fixed cost cap, backups and bandwidth included.
MongoDB Atlas Dedicated (M10)~57 – 58 USD/monthThe lowest dedicated cluster, supports continuous backup.
Neon / Supabase (PostgreSQL – Free tier)0 USDStorage from 0.5 GB, with compute-time limits or automatic pausing after a period of inactivity.

5. What level a Java developer needs when using MongoDB

The skills required depend heavily on who operates the MongoDB cluster. If you use managed services such as Atlas, a Java developer who understands document structure and backend design is fully capable of doing the job. If you self-host and self-maintain a cluster with sharding, replicas, and multiple nodes, you should have someone dedicated to managing it.

Breakdown by experience level (applies when the project uses MongoDB)

LevelExpected MongoDB skillsPractical capability
Junior (0 - 1 year)Understands documents, collections, BSON. Basic CRUD with Spring Data MongoDB (MongoRepository, MongoTemplate). Uses Compass.Develops features on an existing cluster, with code review.
Mid-level (2 - 4 years)Schema design (embedded vs referenced), the ESR rule for indexes, aggregation pipeline, reading explain(), connection pool tuning.Designs and owns the backend independently, handles slow queries.
Senior / Architect (5+ years)Choosing shard keys, designing large-scale models, Change Streams integrated with Kafka, pricing and optimizing Atlas costs.Designs the overall architecture, leads the technical team.

6. MongoDB today in numbers

MetricRecorded value
Total fiscal-year revenue~2.46 billion USD (steady growth of ~23%)
Atlas service growthAbout 29% (accounts for most of the revenue share)
Total number of customersOver 70,600 customers worldwide
Customers with ARR of 1 million USD or moreOver 400 large customers

7. Market forecast through 2036

The NoSQL market is expected to keep a compound annual growth rate (CAGR) of 15% to 20%. For MongoDB specifically, the revenue scenario points to roughly 9 to 10 billion USD by fiscal year 2036, based on a strategy of expanding multi-cloud infrastructure and integrating AI/Agent applications.

8. Technical comparison: MongoDB vs PostgreSQL

CriteriaMongoDBPostgreSQL
Data modelJSON/BSON documents, flexible schemaRelational tables (RDBMS), with added JSONB support
ACID transactionsGood multi-document support, continuously improvingCore, extremely powerful and consistent
Horizontal scaling (scale-out)Built-in, native shardingNeeds partitioning or dedicated extensions (such as Citus)
Vector & AIAtlas Vector SearchThe popular pgvector extension

10. Which one should you choose for your project

  • Choose PostgreSQL when: The system is highly relational, needs complex SQL reporting and absolute data-integrity constraints (for example: core banking, accounting).
  • Choose MongoDB when: Your data consists of complex nested documents, the schema changes constantly with features, and you need fast development and large horizontal write scale-out.

11. Notes on reading forecasts

  • NoSQL market figures from research organizations may vary within a range depending on the survey methodology.
  • Long-term growth scenarios are simulations meant to indicate technology trends.

12. Conclusion

In short, the success of both MongoDB and PostgreSQL shows that there is no single “silver bullet” for every problem.

  1. On trends:
    PostgreSQL has the clearest upward momentum among the leaders: it gained the most popularity points on DB-Engines in the first half of 2026, and it is the only one of the top four to gain points year over year, while Oracle, MySQL, and SQL Server all declined.
    MongoDB is a different story: community interest is no longer surging, but it remains number one in the document store category and its revenue is accelerating. Q2 of fiscal 2027 reached $771.8 million, up 30%, with Atlas growing about 29%.
    This resembles Oracle in that popularity and revenue are moving in opposite directions: Oracle’s multicloud database business grew 353% even as its popularity score declined. The common driver is the shift of workloads to the cloud (Atlas runs on AWS, Azure, and Google Cloud; Oracle runs its Database directly inside AWS and Azure), along with data demand from AI/Agent applications.
    (Data sources: DB-Engines, first half of 2026; MongoDB, quarter ended July 31, 2026; Oracle, quarter ended August 31, 2026.)
  2. On choosing:
    Don’t choose based on trends or on the rumor that it’s “good for an MVP”.
    Start from your data shape, query patterns, and cost at the first paid tier you plan to use.
    The more relational your data, the better PostgreSQL fits; the more your data looks like independent documents that change constantly and need to scale horizontally, the stronger the case for MongoDB.
    Factor in staffing as well: with Atlas, a Java developer with solid fundamentals is enough, whereas self-managing a multi-node cluster requires dedicated DevOps and MongoDB database administration expertise.

With both PostgreSQL and MongoDB growing steadily, the right question is not “which one wins” but “which one fits my problem.” Start from the real problem of your own project to make the most accurate architectural decision.

References

  • MongoDB, Inc. SEC filings & periodic financial reports.
  • Stack Overflow Developer Survey.
  • DB-Engines Ranking of database popularity.
  • International NoSQL market analysis reports.

Thứ Sáu, 2 tháng 10, 2026

Python 2025–2036: Usage Trends

Vietnamese

Python 2025–2036 is a topic worth watching as AI reshapes how engineering teams choose programming languages.

Python has not hit its “final peak” in 2025; more likely, 2025 marks a turning point in its role: Python’s share of total workload shrinks while its position in AI and Data deepens. This view draws on the Stack Overflow Developer Survey 2025 and GitHub Octoverse 2025. The article sketches a scenario in which workloads are layered across Python, TypeScript, Go, Rust, Java and C/C++ through 2036.

Python 2025–2036: Xu hướng sử dụng

Tiếng Anh

Python 2025–2036 là chủ đề đáng quan tâm vào lúc AI đang thay đổi cả cách các nhóm kỹ thuật chọn ngôn ngữ lập trình.

Python chưa chạm “đỉnh cuối cùng” vào năm 2025; nhiều khả năng đó là điểm ngoặt về vai trò: Python giảm tỷ trọng trong tổng workload nhưng đào sâu vị trí ở AI và Data. Nhận định dựa trên Stack Overflow Developer Survey 2025 và GitHub Octoverse 2025. Bài viết phác thảo một kịch bản phân tầng workload giữa Python, TypeScript, Go, Rust, Java và C/C++ đến năm 2036.

1. Python có thực sự đạt đỉnh năm 2025?

Năm 2025 là một năm đặc biệt đối với Python, nhưng gọi đó là “đỉnh cao cuối cùng” thì còn quá sớm. Hai nguồn dữ liệu chính cho thấy một bức tranh phức tạp hơn:

Stack Overflow Developer Survey 2025

Python tăng khoảng 7 điểm phần trăm so với 2024, nhờ AI, Data Science và backend.

GitHub Octoverse 2025

TypeScript lần đầu vượt Python và JavaScript để trở thành ngôn ngữ có nhiều contributor hàng tháng nhất vào tháng 8/2025. Python vẫn tăng rất mạnh (khoảng 2,6 triệu contributor, +48,8% YoY, tức Year-over-Year: so với cùng kỳ năm trước) nhưng TypeScript còn tăng nhanh hơn (+66,6% YoY).

Contributor hàng tháng trên GitHub, 2025:

Ngôn ngữ Contributor / tháng Tăng trưởng YoY
TypeScript ≈ 2,64 triệu +66,6%
Python ≈ 2,6 triệu +48,8%
JavaScript ≈ 2,15 triệu +24,8%
C# — +22,2%
Java — +20,7%

YoY = Year-over-Year: mức tăng so với cùng kỳ năm trước.

Trong các repository AI trên GitHub: Python vẫn áp đảo, đứng sau gần một nửa số AI repository mới.

Ngôn ngữ AI repository Tăng trưởng YoY
Python ≈ 582.000 +50,7%
JavaScript ≈ 88.000 —
TypeScript ≈ 86.000 +77,9%
C++ — Vẫn hiện diện ở tầng hiệu năng cao

Như vậy có hai xu hướng cùng tồn tại, và hai ngôn ngữ không nhất thiết phải cạnh tranh trực tiếp với nhau:

Software 2025: Application (TypeScript/JS) và AI (Python)

Cách diễn giải hợp lý hơn: 2025 có thể là điểm ngoặt về vai trò của Python, chứ chưa đủ bằng chứng để gọi đó là đỉnh tuyệt đối về mức sử dụng.

Python có thể đang chuyển từ “ngôn ngữ đa năng” sang “ngôn ngữ nền tảng của AI/Data và orchestration”, trong khi TypeScript mở rộng mạnh ở Application, Full-stack và AI Application. Vì vậy, câu hỏi quan trọng cho giai đoạn 2025–2036 là:

Những loại workload nào sẽ tiếp tục thuộc về Python, và những workload nào sẽ chuyển sang TypeScript, Go, Rust, Java hoặc C++?

2. “Thị phần” ngôn ngữ lập trình đo bằng gì?

Không có một chỉ số duy nhất gọi là market share của ngôn ngữ lập trình. Các nguồn phổ biến đo những thứ khác nhau:

Nguồn Chủ yếu đo Ý nghĩa
Stack Overflow Developer đã sử dụng ngôn ngữ Developer adoption
GitHub Contributor / repository / code activity Hoạt động phát triển
TIOBE Popularity dựa trên nhiều tín hiệu web Popularity indicator
PYPL Tìm kiếm tutorial trên Google Learning / popularity indicator

TIOBE nhấn mạnh rằng chỉ số của họ không phải tỷ lệ code được viết bằng một ngôn ngữ, mà là chỉ báo mức độ phổ biến dựa trên kỹ sư, khóa học, nhà cung cấp và nhiều nguồn web. PYPL được xây dựng từ lượt tìm tutorial trên Google nên cũng không thể xem là thị phần phần mềm. Do đó, bảng dự báo ở mục 3 nên được hiểu là:

Dự báo tỷ trọng tương đối của workload / code activity trong một nhóm ngôn ngữ chính, không phải dự báo doanh thu của toàn bộ thị trường phần mềm.

3. Dự báo Top 10: 2025 → 2026 → 2030 → 2036

Bảng dưới đây là kịch bản dự báo, không phải số liệu chính thức. Tôi điều chỉnh dự báo theo các tín hiệu mới từ GitHub, Stack Overflow và xu hướng AI-assisted development.

Ngôn ngữ 2025 2026 2030 2036
JavaScript 20.6% 19.5% 17.4% 16.5%
Python 18.1% 18.1% 14.8% 12.3%
TypeScript 13.6% 14.1% 20.5% 23.5%
Java 9.2% 8.7% 9.0% 9.8%
C# 8.7% 8.5% 8.6% 9.0%
C++ 7.3% 7.7% 7.6% 7.6%
C 6.9% 6.9% 6.0% 5.0%
Rust 4.6% 5.7% 6.2% 6.8%
PHP 5.9% 5.6% 4.4% 3.5%
Go 5.1% 5.2% 5.5% 6.0%
Tổng 100% 100% 100% 100%

Ghi chú: 2030 và 2036 giả định TypeScript tiếp tục tăng thị phần, Python giảm, còn Java, Go và Rust tăng chậm. JavaScript chỉ giảm nhẹ vì một phần công việc chuyển sang TypeScript, nhưng vẫn được dùng nhiều trong các dự án SSR và hybrid.

Cách đọc bảng. Đây là tỷ trọng tương đối trong một “Top-10 workload basket”, không phải:

  • tỷ lệ developer sử dụng ngôn ngữ;
  • tỷ lệ repository;
  • tỷ lệ GitHub contributor;
  • hay “thị phần” tuyệt đối của toàn ngành phần mềm.

Bảng nhằm trả lời một câu hỏi khác: nếu xét tổng workload phát triển phần mềm của các ngôn ngữ lớn, workload tương đối có thể dịch chuyển như thế nào từ 2025 đến 2036?

4. Python: giảm tỷ trọng nhưng chưa giảm vai trò

Một phần workload tổng quát của Python có thể chuyển sang TypeScript, Go và Rust. Phạm vi của Python vì thế có thể thu hẹp nhưng sâu hơn:

2025 — Python “rộng”

  • AI / ML
  • Data
  • Automation
  • Backend
  • General-purpose

2036 — Python “sâu”

  • AI / ML
  • Data Science
  • Research
  • AI orchestration
  • Scientific computing

Điểm tựa của Python là network effect rất lớn của hệ sinh thái:

  • Thư viện và framework: NumPy, Pandas, PyTorch, TensorFlow, JAX, Hugging Face
  • Công cụ: Jupyter
  • Cộng đồng: hàng triệu notebook, tutorial và package

GitHub vẫn mô tả Python là ngôn ngữ chủ đạo của AI và Data Science.

Số lượng tăng nhưng tỷ trọng vẫn có thể giảm

Số developer Python, workload AI, Data và ML đều có thể tăng. Nhưng nếu tổng workload của toàn ngành tăng nhanh hơn, tỷ trọng của Python vẫn giảm. Tương tự, Python tổng thể có thể giảm tỷ trọng trong khi hệ sinh thái PyTorch / AI tăng vai trò. Hai điều này không mâu thuẫn:

  • Có thể mất: generic scripting, backend đơn giản, một phần automation và infrastructure
  • Giữ lại: ML, AI, Data, Research, training, experimentation, AI orchestration

Lý do không chỉ nằm ở cú pháp Python mà ở network effect của hệ sinh thái.

5. TypeScript: ứng viên lớn nhất để lấy workload mới

Đây có thể là thay đổi quan trọng nhất trong application development. GitHub ghi nhận TypeScript đứng đầu theo contributor từ tháng 8/2025. GitHub liên hệ xu hướng này với sự phổ biến của các framework dùng TypeScript mặc định và nhu cầu type safety trong thời đại AI-assisted development.

AI đang làm thay đổi lợi thế truyền thống của Python:

Trước AI

Developer viết code → Python thắng vì viết nhanh.

Sau AI

Developer → AI tạo code → review / test / type-check → production.

Khi AI viết được code bằng nhiều ngôn ngữ, lợi thế “dễ viết” của Python giảm tương đối. GitHub cũng cho rằng typed languages cung cấp thêm guardrails cho code do AI tạo ra.

TypeScript có thể mở rộng sang Web, Full-stack, Node.js, SaaS, AI application, AI agent, tooling và automation, vì đáp ứng những thứ AI-assisted development đang cần:

  • Type safety và static analysis
  • IDE support và refactoring
  • API contracts
  • Bảo trì codebase lớn
  • Kiểm chứng code do AI tạo ra

Nói cách khác, TypeScript lấy phần application engineering mà Python từng có lợi thế. Hệ quả: workload tổng quát có thể dịch chuyển sang TypeScript / Go / Rust, còn workload AI / ML / Data vẫn thuộc về Python. Một mô hình ba tầng hợp lý hơn:

Tầng 1 — Ứng dụng AI

Web, SaaS, Mobile, Chat UI; AI Agent, RAG, tool calling, orchestration, MCP, API.

TypeScript (React, Next.js, Node.js, Vercel AI SDK) → “DÙNG AI để làm sản phẩm”.

↓ REST / Streaming API ↓

Tầng 2 — Model & AI development

Data pipeline, training, fine-tuning, evaluation; model serving / inference (vLLM, TensorRT-LLM).

Python (PyTorch, JAX, Hugging Face, NumPy, Pandas), lõi tính toán bên dưới là C++/CUDA → “TẠO RA và VẬN HÀNH AI”.

↓ Runtime / Driver ↓

Tầng 3 — Hạ tầng & phần cứng

Kubernetes, Docker, Ray, Slurm, Cloud; GPU, CPU, NPU/TPU, RAM, VRAM, SSD.

C++ / CUDA (driver, kernel, thư viện hiệu năng) → “Làm AI CHẠY được và chạy NHANH”.

6. Go, Rust, Java, C# và C/C++: mỗi ngôn ngữ giữ một tầng

Go — lấy workload ở Cloud / Infrastructure

Go có thể hưởng lợi từ Cloud, Kubernetes, networking, microservices, API gateway, distributed systems, AI serving và developer infrastructure. Mô hình phổ biến: Python làm prototype, rồi khi lên production với yêu cầu high concurrency hoặc deployment thì chuyển sang Go.

Không nhất thiết Go thay Python; hai ngôn ngữ có thể chia tầng: Python → AI / automation / data; Go → infrastructure / serving. Go có thể trở thành một trong những ngôn ngữ hạ tầng quan trọng nhất.

Rust — ít workload hơn nhưng có giá trị ở tầng khó

Rust có khả năng tăng trưởng ở systems, security, networking, database, runtime, WASM, edge và AI infrastructure. Stack Overflow 2025 tiếp tục xếp Rust là ngôn ngữ được “admired” cao nhất (72%), và cho thấy Python developers có xu hướng hướng tới Rust và Go khi đi vào high-performance systems programming.

Khi AI tạo ra ngày càng nhiều code, nhu cầu về memory safety và correctness có thể khiến Rust hấp dẫn hơn ở các workload đòi hỏi performance + memory safety + concurrency + security.

Java — giữ tỷ trọng ổn định và tăng nhẹ lên tới 9.8%

Java phù hợp với banking, fintech, ERP, government, enterprise, e-commerce, high-load backend và distributed systems, với installed base rất lớn. Cần phân biệt:

Mức phổ biến của dự án mới ≠ installed base đang chạy production

Một hệ thống ngân hàng đang chạy Java/Spring không tự biến mất chỉ vì một bảng popularity giảm vài điểm. Kịch bản hợp lý đến 2036: Java duy trì thị phần ổn định, mặc dù đang mất dần vị thế tại một số dự án mới hoàn toàn, nhưng vẫn mạnh ở enterprise và high-load systems.

Ý kiến cá nhân: trong mảng thương mại điện tử, tôi vẫn thiên về Java hơn Node.js ở tầng backend.

C# — tăng đều đều, tiến sát Java

C# ít “ồn ào” nhưng tăng đều: contributor GitHub tăng +22,2% YoY, nhanh hơn Java (+20,7%). Hệ sinh thái .NET, Azure, Unity / game development, ứng dụng desktop và công cụ nội bộ doanh nghiệp tạo cho C# một installed base lớn và ổn định.

Trong kịch bản của bài, C# tăng nhẹ từ 8,7% (2025) lên khoảng 9,0% (2036), tiến sát Java (9,8%) nhưng chưa vượt. Lý do: C# xuất phát thấp hơn một chút, dù tốc độ tăng cao hơn.

Ở mảng enterprise, C# và Java có thể cùng chia phần: Java mạnh ở banking, fintech, high-load backend; C# mạnh ở hệ sinh thái Microsoft, game và ứng dụng doanh nghiệp. Hai ngôn ngữ này ít bị TypeScript hay Go lấy workload hơn so với Python, vì gắn chặt với hệ sinh thái và công cụ riêng.

C / C++ — vẫn giữ vị trí đặc biệt

AI càng phát triển thì tầng dưới càng cần GPU, CUDA, runtime, compiler, inference, robotics, embedded, edge và game engine; C/C++ giữ vai trò lớn ở các tầng này.

Chuỗi gọi điển hình của một ứng dụng AI:

App (TypeScript) → API → Inference runtime → C++/CUDA → GPU

Còn với Python, chuỗi gọi như sau:

Python, TypeScript, Java, C#, PHP...              ← Application layer
   ↓ gọi hàm
AI framework (PyTorch...)                         ← Framework layer
   │  (Python API + C++ core, gọi qua pybind11)
   ↓ gọi thư viện đã biên dịch
C++ / CUDA libs (cuDNN, cuBLAS, CUDA Runtime)     ← Library layer
   │  (file .so trên SSD, nạp vào RAM khi chạy)
   ↓ gửi kernel + dữ liệu qua driver
GPU Driver (NVIDIA: user-mode + kernel-mode)      ← Infrastructure layer
   ↓ PCIe / NVLink
GPU (phần cứng, thực thi kernel)                  ← Hardware layer

Ngăn xếp thực thi AI này cho biết cách Python tận dụng native performance mà vẫn giữ được developer experience.

Ở tầng cao hơn, AI framework như PyTorch cung cấp các API để xây dựng mô hình, biểu diễn tensor và xác định các phép tính trong quá trình huấn luyện hoặc suy luận. Framework chịu trách nhiệm điều phối quá trình thực thi và quản lý dữ liệu, đồng thời sử dụng các backend và thư viện tối ưu hóa như CUDA, cuBLAS và cuDNN khi cần tăng tốc trên GPU.

Ở các tầng thấp hơn, CUDA Runtime, các thư viện tính toán và GPU Driver phối hợp để cấp phát bộ nhớ, thiết lập và gửi công việc thực thi đến GPU. GPU sau đó trực tiếp thực hiện các kernel tính toán trên dữ liệu đã được đưa vào bộ nhớ phù hợp.

Nhờ kiến trúc phân lớp này, lập trình viên có thể làm việc chủ yếu với Python và PyTorch mà không cần trực tiếp quản lý từng lệnh GPU hay tự viết CUDA kernel cho mọi phép tính.

7. Python không cần tự trở thành C++

Python có một điểm yếu nổi tiếng: raw CPU performance thấp hơn C/C++/Rust. Giải pháp không phải là bỏ Python mà là đưa phần tính toán nặng xuống tầng native:

  • Trong CPython: tối ưu CPython, JIT, free-threading
  • Biên dịch / tăng tốc: Numba, Cython (đưa đoạn code giống Python xuống C/C++)
  • Native extensions: C/C++, Rust
  • Ngôn ngữ mới: Mojo, theo hướng compiled cho systems / AI và heterogeneous computing

Khi đó, Python có thể tiếp tục là entry point, còn phần computation nặng được thực thi bởi native code hoặc accelerator (CPU / GPU / NPU).

8. Software 2036 có thể được phân tầng

Thay vì để Python, TypeScript, Java, Go và Rust cạnh tranh trực tiếp, có thể nhìn chúng như các tầng của cùng một hệ thống. Đây có thể là mô hình có ý nghĩa hơn việc tìm một “ngôn ngữ số 1”. Trong sơ đồ bên dưới, TypeScript đại diện cho tầng Web / Application. Trong tầng này, TypeScript dẫn đầu về mức sử dụng kỳ vọng (expected usage), tiếp theo là chín ngôn ngữ còn lại theo thứ tự giảm dần: C#, Java, Python, PHP, Ruby, Go, Elixir, Kotlin và Rust.

Software 2036 phân tầng: TypeScript, Java/Go, Rust/Python, C/C++, GPU

9. Ngôn ngữ nào có thể lấy workload từ Python?

Đây là kịch bản chủ quan, không phải thống kê thị trường:

Ngôn ngữ Khả năng nhận workload từ Python Khu vực chính
TypeScript 30–40% Web, backend, AI application, Agent
Go 20–25% Cloud, infrastructure, microservices, serving
Rust 15–20% Performance, systems, security
Java 10–15% Enterprise, high-load, AI integration
C++ 5–10% Runtime, inference, GPU, robotics
Khác 5–10% C#, Kotlin, Swift, Zig...

Các tỷ lệ này là cách chia gần đúng phần workload Python có thể dịch chuyển trong giai đoạn 2026–2036 (tổng xấp xỉ 100% ở mức trung bình), không phải thị phần của Python hay của các ngôn ngữ kia.

10. Roadmap 2025–2036 của Python

  • ● 2025: Python bùng nổ nhờ AI / Data.
  • ● 2026–2028: TypeScript tăng mạnh; Python tiếp tục tăng trong AI; JIT, CPython và native extensions tiếp tục cải thiện.
  • ● 2029–2032: Python phân hóa workload: AI/Data → Python; Application → TypeScript; Cloud/Infra → Go; Systems → Rust/C++; Enterprise → Java/C#.
  • ● 2033–2036: Python trở thành ngôn ngữ nền tảng của AI/Data; phần thực thi nặng do native code (C++, Rust, Cython, Mojo, GPU) đảm nhận.

11. Kịch bản năm 2036

Nếu kịch bản trên xảy ra, bức tranh có thể là:

Lĩnh vực Ngôn ngữ nổi bật
AI / ML / Data Python
Web / Application TypeScript, C#, Java, Python, PHP, Ruby
AI Agent / Application TypeScript + Python
Enterprise Java + C#
Backend / Services (web, AI app) TypeScript (Node.js), Java, C#, Python, Go, PHP
Backend / Services (high-load) Java + Go
Cloud / Infrastructure Go + Rust
Systems / Security Rust + C + C++
GPU / AI Runtime C++/CUDA + native/DSL
Scientific Computing Python + native backends
Mobile TypeScript (React Native), Dart (Flutter), Swift, Kotlin
Desktop TypeScript (Electron/Tauri), C#, Swift, C++/Qt, Rust (Tauri)

Ghi chú: ô liệt kê cách nhau bằng dấu phẩy được xếp theo mức độ sử dụng dự kiến, ngôn ngữ in đậm là dẫn đầu. Ô nối bằng dấu "+" gồm các ngôn ngữ giữ vai trò ngang nhau hoặc dùng song hành.

Kết luận

Nhìn tổng thể, Python có thể giảm tỷ trọng trong tổng workload nhưng vẫn tiếp tục tăng ở AI và Data Science, vị trí cốt lõi của Python. Đối thủ nặng ký nhất là TypeScript: đã vượt Python về contributor trên GitHub từ năm 2025 và, theo kịch bản của bài viết, có thể chiếm khoảng 23,5% workload vào năm 2036 so với 15,5% của Python.

Câu hỏi đến năm 2036 vì thế có thể là: “Python sẽ giữ tầng nào trong software stack?”

Với dữ liệu hiện có, câu trả lời có cơ sở nhất là: Python có khả năng tiếp tục giữ một tầng rất quan trọng ở AI/Data, trong khi các ngôn ngữ khác cạnh tranh mạnh hơn ở Application, Cloud, Infrastructure và Systems.

Nguồn tham khảo

  • Stack Overflow Developer Survey 2025 — dữ liệu developer adoption và xu hướng Python.
  • GitHub Octoverse 2025 — TypeScript #1 theo monthly contributors; Python vẫn thống trị AI repositories.
  • GitHub — TypeScript/Python and AI feedback loop — phân tích thay đổi lựa chọn ngôn ngữ trong thời đại AI-assisted development.
  • TIOBE Index — chỉ số popularity, cần phân biệt với market share thực tế.
  • PYPL — chỉ số dựa trên tìm kiếm tutorial, phù hợp để tham khảo xu hướng popularity / learning.

Ghi chú phương pháp

Các con số 2026/2030/2036 trong bài là scenario forecast của cá nhân tác giả, không phải dự báo chính thức của Stack Overflow, GitHub, TIOBE, PYPL, hay dự báo của tổ chức nào. Với horizon 10 năm, thay đổi về AI, compiler, hardware, agentic programming và các ngôn ngữ mới có thể làm sai lệch đáng kể mọi ngoại suy hiện tại.

PHỔ BIẾN

NHÃN

LƯỢT XEM