<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lettuce: 深度解析与实战指南</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Crimson+Text:ital,wght@0,400;0,600;1,400;1,600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
<style>
:root {
--primary: #2563eb;
--secondary: #64748b;
--accent: #dc2626;
--neutral: #1e293b;
--base-100: #ffffff;
--base-200: #f8fafc;
--base-300: #e2e8f0;
}
body {
font-family: 'Inter', sans-serif;
line-height: 1.7;
color: var(--neutral);
overflow-x: hidden;
}
.serif-italic {
font-family: 'Crimson Text', serif;
font-style: italic;
}
.toc-sidebar {
position: fixed;
top: 0;
left: 0;
width: 280px;
height: 100vh;
background: var(--base-100);
border-right: 1px solid var(--base-300);
z-index: 1000;
overflow-y: auto;
padding: 2rem 1.5rem;
}
.main-content {
margin-left: 280px;
min-height: 100vh;
}
.toc-item {
display: block;
padding: 0.5rem 0;
color: var(--secondary);
text-decoration: none;
border-left: 2px solid transparent;
padding-left: 1rem;
transition: all 0.2s ease;
}
.toc-item:hover {
color: var(--primary);
border-left-color: var(--primary);
background: rgba(37, 99, 235, 0.05);
}
.toc-item.level-2 {
padding-left: 2rem;
font-size: 0.9rem;
}
.toc-item.level-3 {
padding-left: 3rem;
font-size: 0.85rem;
}
.hero-grid {
display: grid;
grid-template-columns: 2fr 1fr;
gap: 2rem;
align-items: center;
min-height: 60vh;
}
.code-block {
background: #1e293b;
color: #e2e8f0;
border-radius: 8px;
padding: 1.5rem;
overflow-x: auto;
font-family: 'SF Mono', 'Menlo', 'Monaco', monospace;
font-size: 0.9rem;
line-height: 1.6;
}
.citation {
color: var(--primary);
text-decoration: none;
font-weight: 500;
border-bottom: 1px dotted var(--primary);
}
.citation:hover {
background: rgba(37, 99, 235, 0.1);
}
.performance-card {
background: var(--base-100);
border: 1px solid var(--base-300);
border-radius: 12px;
padding: 1.5rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.quote-block {
border-left: 4px solid var(--accent);
background: rgba(220, 38, 38, 0.05);
padding: 1.5rem;
margin: 2rem 0;
border-radius: 0 8px 8px 0;
}
<span class="mention-invalid">@media</span> (max-width: 1024px) {
.toc-sidebar {
display: none;
}
.main-content {
margin-left: 0;
}
.hero-grid {
grid-template-columns: 1fr;
}
}
<span class="mention-invalid">@media</span> (max-width: 768px) {
.mermaid-control-btn:not(.reset-zoom) {
display: none;
}
.mermaid-controls {
top: auto;
bottom: 15px;
right: 15px;
}
}
.section-divider {
height: 1px;
background: linear-gradient(90deg, transparent, var(--base-300), transparent);
margin: 3rem 0;
}
.mermaid-container {
display: flex;
justify-content: center;
min-height: 300px;
max-height: 800px;
background: #ffffff;
border: 2px solid #e5e7eb;
border-radius: 12px;
padding: 30px;
margin: 30px 0;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.08);
position: relative;
overflow: hidden;
}
.mermaid-container .mermaid {
width: 100%;
max-width: 100%;
height: 100%;
cursor: grab;
transition: transform 0.3s ease;
transform-origin: center center;
display: flex;
justify-content: center;
align-items: center;
touch-action: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.mermaid-container .mermaid svg {
max-width: 100%;
height: 100%;
display: block;
margin: 0 auto;
}
.mermaid-container .mermaid:active {
cursor: grabbing;
}
.mermaid-container.zoomed .mermaid {
height: 100%;
width: 100%;
cursor: grab;
}
.mermaid-controls {
position: absolute;
top: 15px;
right: 15px;
display: flex;
gap: 10px;
z-index: 20;
background: rgba(255, 255, 255, 0.95);
padding: 8px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.mermaid-control-btn {
background: #ffffff;
border: 1px solid #d1d5db;
border-radius: 6px;
padding: 10px;
cursor: pointer;
transition: all 0.2s ease;
color: #374151;
font-size: 14px;
min-width: 36px;
height: 36px;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
.mermaid-control-btn:hover {
background: #f8fafc;
border-color: #3b82f6;
color: #3b82f6;
transform: translateY(-1px);
}
.mermaid-control-btn:active {
transform: scale(0.95);
}
.mermaid-container {
display: flex;
justify-content: center;
min-height: 300px;
max-height: 800px;
background: #ffffff;
border: 2px solid #e5e7eb;
border-radius: 12px;
padding: 30px;
margin: 30px 0;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.08);
position: relative;
overflow: hidden;
}
.mermaid-container .mermaid {
width: 100%;
max-width: 100%;
height: 100%;
cursor: grab;
transition: transform 0.3s ease;
transform-origin: center center;
display: flex;
justify-content: center;
align-items: center;
touch-action: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.mermaid-container .mermaid svg {
max-width: 100%;
height: 100%;
display: block;
margin: 0 auto;
}
.mermaid-container .mermaid:active {
cursor: grabbing;
}
.mermaid-container.zoomed .mermaid {
height: 100%;
width: 100%;
cursor: grab;
}
.mermaid-controls {
position: absolute;
top: 15px;
right: 15px;
display: flex;
gap: 10px;
z-index: 20;
background: rgba(255, 255, 255, 0.95);
padding: 8px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.mermaid-control-btn {
background: #ffffff;
border: 1px solid #d1d5db;
border-radius: 6px;
padding: 10px;
cursor: pointer;
transition: all 0.2s ease;
color: #374151;
font-size: 14px;
min-width: 36px;
height: 36px;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
.mermaid-control-btn:hover {
background: #f8fafc;
border-color: #3b82f6;
color: #3b82f6;
transform: translateY(-1px);
}
.mermaid-control-btn:active {
transform: scale(0.95);
}
</style>
<base target="_blank">
</head>
<body class="bg-gray-50">
<!-- Table of Contents Sidebar -->
<div class="toc-sidebar">
<h3 class="text-lg font-semibold mb-4 text-gray-900">目录导航</h3>
<nav>
<a href="#introduction" class="toc-item">引言</a>
<a href="#core-architecture" class="toc-item">1. 核心架构与设计思想</a>
<a href="#netty-model" class="toc-item level-2">1.1 基于Netty的异步事件驱动模型</a>
<a href="#connection-management" class="toc-item level-2">1.2 连接管理与多路复用</a>
<a href="#thread-safety" class="toc-item level-2">1.3 线程安全与可伸缩性</a>
<a href="#features-api" class="toc-item">2. 功能特性与API详解</a>
<a href="#api-support" class="toc-item level-2">2.1 多样化的API支持</a>
<a href="#advanced-features" class="toc-item level-2">2.2 高级功能特性</a>
<a href="#usage-demos" class="toc-item">3. 使用Demo与最佳实践</a>
<a href="#environment-setup" class="toc-item level-2">3.1 环境准备与依赖引入</a>
<a href="#single-instance" class="toc-item level-2">3.2 连接Redis单机实例</a>
<a href="#cluster-mode" class="toc-item level-2">3.3 连接Redis集群</a>
<a href="#pipelining" class="toc-item level-2">3.4 管道(Pipelining)模式使用</a>
<a href="#comparison" class="toc-item">4. 对比分析:Lettuce vs. Jedis</a>
<a href="#performance-comparison" class="toc-item level-2">4.1 性能对比</a>
<a href="#features-comparison" class="toc-item level-2">4.2 功能与易用性对比</a>
<a href="#scenario-analysis" class="toc-item level-2">4.3 适用场景与选型建议</a>
</nav>
</div>
<!-- Main Content -->
<div class="main-content">
<!-- Hero Section -->
<section class="bg-gradient-to-br from-blue-50 to-white py-16 px-8">
<div class="max-w-6xl mx-auto">
<div class="hero-grid">
<div>
<h1 class="text-5xl font-bold text-gray-900 mb-6 leading-tight">
<span class="serif-italic text-red-600">Lettuce</span>
<br>
深度解析与实战指南
</h1>
<p class="text-xl text-gray-600 mb-8 leading-relaxed">
基于 Netty 的高性能异步 Redis Java 客户端,为现代微服务架构而生的响应式数据访问解决方案
</p>
<!-- Key Highlights Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
<div class="performance-card">
<div class="flex items-center mb-2">
<i class="fas fa-rocket text-blue-600 mr-3"></i>
<h4 class="font-semibold">高性能</h4>
</div>
<p class="text-sm text-gray-600">非阻塞 I/O,单连接支撑 7000+ QPS</p>
</div>
<div class="performance-card">
<div class="flex items-center mb-2">
<i class="fas fa-sync text-green-600 mr-3"></i>
<h4 class="font-semibold">异步支持</h4>
</div>
<p class="text-sm text-gray-600">原生异步与响应式 API</p>
</div>
<div class="performance-card">
<div class="flex items-center mb-2">
<i class="fas fa-shield-alt text-purple-600 mr-3"></i>
<h4 class="font-semibold">线程安全</h4>
</div>
<p class="text-sm text-gray-600">连接多路复用,资源高效</p>
</div>
<div class="performance-card">
<div class="flex items-center mb-2">
<i class="fas fa-cogs text-orange-600 mr-3"></i>
<h4 class="font-semibold">Spring 默认</h4>
</div>
<p class="text-sm text-gray-600">Spring Boot 2.x+ 官方推荐</p>
</div>
</div>
</div>
<div class="relative">
<img src="https://kimi-img.moonshot.cn/pub/icon/spinner.svg" alt="Redis客户端架构抽象示意图" class="rounded-lg shadow-xl w-full h-96 object-cover" size="large" aspect="wide" query="Redis客户端架构抽象图" referrerpolicy="no-referrer" />
<div class="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent rounded-lg"></div>
</div>
</div>
</div>
</section>
<!-- Introduction -->
<section id="introduction" class="py-16 px-8 bg-white">
<div class="max-w-4xl mx-auto">
<div class="quote-block">
<p class="text-lg serif-italic text-gray-700">
"Lettuce 是一个基于 Netty 的、高性能、异步且线程安全的 Redis Java 客户端。它通过非阻塞 I/O 和连接多路复用,在高并发场景下提供卓越的吞吐量和资源效率。"
</p>
</div>
<div class="prose prose-lg max-w-none">
<p class="text-gray-700 leading-relaxed mb-6">
与 Jedis 相比,Lettuce 不仅支持同步 API,还提供了强大的异步和响应式 API,使其成为现代微服务、云原生和响应式架构的理想选择。自 Spring Boot 2.x 起,Lettuce 已成为其默认的 Redis 客户端。
</p>
<div class="bg-blue-50 p-6 rounded-lg border-l-4 border-blue-500">
<h3 class="text-lg font-semibold text-blue-900 mb-2">核心优势概览</h3>
<ul class="list-disc list-inside text-blue-800 space-y-2">
<li><strong>异步事件驱动:</strong>基于 Netty 的非阻塞 I/O 架构</li>
<li><strong>连接多路复用:</strong>单连接支撑高并发请求</li>
<li><strong>原生线程安全:</strong>无需连接池,简化开发</li>
<li><strong>响应式支持:</strong>完美集成 Reactor 生态系统</li>
<li><strong>企业级特性:</strong>集群、哨兵、SSL 等生产环境必备功能</li>
</ul>
</div>
</div>
</div>
</section>
<div class="section-divider"></div>
<!-- Core Architecture -->
<section id="core-architecture" class="py-16 px-8">
<div class="max-w-6xl mx-auto">
<h2 class="text-4xl font-bold text-gray-900 mb-8 serif-italic">核心架构与设计思想</h2>
<p class="text-xl text-gray-600 mb-12 leading-relaxed">
Lettuce 的卓越性能和丰富功能根植于其先进的架构设计和前瞻性的设计理念。
<a href="https://blog.csdn.net/Ethan_199402/article/details/132686833" class="citation" target="_blank">[25]</a>
</p>
<!-- Netty Architecture Diagram -->
<div class="mb-12">
<div class="mermaid-container">
<div class="mermaid-controls">
<button class="mermaid-control-btn zoom-in" title="放大">
<i class="fas fa-search-plus"></i>
</button>
<button class="mermaid-control-btn zoom-out" title="缩小">
<i class="fas fa-search-minus"></i>
</button>
<button class="mermaid-control-btn reset-zoom" title="重置">
<i class="fas fa-expand-arrows-alt"></i>
</button>
<button class="mermaid-control-btn fullscreen" title="全屏查看">
<i class="fas fa-expand"></i>
</button>
</div>
<div class="mermaid">
graph TB
A["业务线程"] --> B["Lettuce API"]
B --> C["CommandHandler"]
C --> D["Netty ChannelPipeline"]
D --> E["EventLoop 单线程"]
E --> F["Redis 服务器"]
D --> G["连接管理"]
D --> H["协议握手"]
D --> I["命令编码"]
D --> J["响应解码"]
K["RESP3 协议"] --> H
L["SSL/TLS"] --> G
M["零拷贝优化"] --> E
style A fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#1e293b
style F fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#1e293b
style E fill:#fef3c7,stroke:#d97706,stroke-width:2px,color:#1e293b
style C fill:#fce7f3,stroke:#ec4899,stroke-width:2px,color:#1e293b
style D fill:#f3e8ff,stroke:#9333ea,stroke-width:2px,color:#1e293b
style B fill:#f8fafc,stroke:#64748b,stroke-width:2px,color:#1e293b
style G fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#1e293b
style H fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#1e293b
style I fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#1e293b
style J fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#1e293b
style K fill:#fef7cd,stroke:#f59e0b,stroke-width:2px,color:#1e293b
style L fill:#fef7cd,stroke:#f59e0b,stroke-width:2px,color:#1e293b
style M fill:#fef7cd,stroke:#f59e0b,stroke-width:2px,color:#1e293b
</div>
</div>
<p class="text-center text-gray-600 text-sm mt-4">
<i class="fas fa-info-circle mr-1"></i>
支持缩放和拖拽操作 • 点击右上角按钮控制视图
</p>
</div>
<!-- Netty-based Async Model -->
<div id="netty-model" class="mb-16">
<h3 class="text-2xl font-semibold text-gray-900 mb-6">基于Netty的异步事件驱动模型</h3>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-8">
<div>
<p class="text-gray-700 mb-4">
Lettuce 完全构建在 Netty 这一强大的异步事件驱动网络应用框架之上。与许多传统的 Redis 客户端(如 Jedis)采用的阻塞 I/O 模型不同,Lettuce 从设计之初就拥抱了非阻塞 I/O。
<a href="https://blog.csdn.net/Ethan_199402/article/details/132686833" class="citation" target="_blank">[25]</a>
</p>
<div class="bg-blue-50 p-4 rounded-lg">
<h4 class="font-semibold text-blue-900 mb-2">Netty 集成优势</h4>
<ul class="list-disc list-inside text-blue-800 space-y-1">
<li>零拷贝(Zero-Copy)特性</li>
<li>内存池化管理</li>
<li>epoll/kqueue 原生支持</li>
<li>SSL/TLS 加密连接</li>
</ul>
</div>
</div>
<div>
<img src="https://kimi-img.moonshot.cn/pub/icon/spinner.svg" alt="Netty网络框架架构图" class="rounded-lg shadow-lg w-full h-64 object-cover" size="medium" aspect="wide" query="Netty网络框架架构" referrerpolicy="no-referrer" />
</div>
</div>
<div class="bg-gray-900 text-gray-100 p-6 rounded-lg mb-6">
<h4 class="text-lg font-semibold mb-4 text-blue-400">ChannelPipeline 处理器链</h4>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
<div>
<h5 class="font-semibold text-green-400 mb-2">出站处理器</h5>
<ul class="space-y-1">
<li>
<code class="bg-gray-800 px-2 py-1 rounded">CommandEncoder</code> - 命令序列化
</li>
<li>
<code class="bg-gray-800 px-2 py-1 rounded">RedisHandshakeHandler</code> - 协议握手
</li>
</ul>
</div>
<div>
<h5 class="font-semibold text-yellow-400 mb-2">入站处理器</h5>
<ul class="space-y-1">
<li>
<code class="bg-gray-800 px-2 py-1 rounded">CommandHandler</code> - 响应解码
</li>
<li>
<code class="bg-gray-800 px-2 py-1 rounded">ConnectionWatchdog</code> - 断线重连
</li>
</ul>
</div>
</div>
</div>
</div>
<!-- Connection Management -->
<div id="connection-management" class="mb-16">
<h3 class="text-2xl font-semibold text-gray-900 mb-6">连接管理与多路复用</h3>
<p class="text-gray-700 mb-6">
Lettuce 在连接管理方面采用了与传统连接池截然不同的策略,其核心是<strong>连接多路复用(Connection Multiplexing)</strong>。与 Jedis 需要维护一个庞大的连接池来为每个线程提供独立的连接不同,Lettuce 的一个连接实例(
<code>StatefulRedisConnection</code>)是线程安全的,可以被多个线程共享。
<a href="https://blog.csdn.net/Ethan_199402/article/details/132686833" class="citation" target="_blank">[25]</a>
</p>
<!-- Connection Multiplexing Performance Comparison -->
<div class="bg-white p-6 rounded-lg shadow-md mb-8">
<h4 class="text-xl font-semibold mb-4">连接多路复用性能对比</h4>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="bg-red-50 p-4 rounded-lg border-l-4 border-red-500">
<h5 class="font-semibold text-red-900 mb-2">Jedis 连接池模式</h5>
<ul class="text-red-800 space-y-1">
<li>• 每个线程需要独立连接</li>
<li>• 连接池管理复杂</li>
<li>• 内存占用高(120MB @ 100 连接)</li>
<li>• 上下文切换开销大</li>
</ul>
</div>
<div class="bg-green-50 p-4 rounded-lg border-l-4 border-green-500">
<h5 class="font-semibold text-green-900 mb-2">Lettuce 多路复用</h5>
<ul class="text-green-800 space-y-1">
<li>• 单连接支持多线程</li>
<li>• 无需连接池管理</li>
<li>• 内存占用低(80MB @ 100 连接)</li>
<li>• 系统资源利用率高</li>
</ul>
</div>
</div>
<p class="text-sm text-gray-600 mt-4">
数据来源:<a href="https://www.cnblogs.com/Chary/articles/19121235" class="citation" target="_blank">[46]</a>
</p>
</div>
<div class="code-block">
<pre><code>// Lettuce 连接多路复用示例
RedisClient redisClient = RedisClient.create("redis://localhost:6379");
StatefulRedisConnection<String, String> connection = redisClient.connect();
// 多个线程可以安全地共享同一个连接
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++) {
executor.submit(() -> {
RedisCommands<String, String> commands = connection.sync();
commands.set("key:" + Thread.currentThread().getId(), "value");
});
}</code></pre>
</div>
</div>
<!-- Thread Safety -->
<div id="thread-safety" class="mb-16">
<h3 class="text-2xl font-semibold text-gray-900 mb-6">线程安全与可伸缩性</h3>
<div class="bg-yellow-50 border-l-4 border-yellow-400 p-6 mb-8">
<h4 class="font-semibold text-yellow-800 mb-2">
<i class="fas fa-lightbulb mr-2"></i>关键设计原则
</h4>
<p class="text-yellow-700">
Lettuce 的核心组件,特别是连接对象(
<code>StatefulRedisConnection</code>),被设计为<strong>线程安全的</strong>。这一特性是其能够实现高效连接复用和卓越可伸缩性的基础。
<a href="https://blog.csdn.net/Ethan_199402/article/details/132686833" class="citation" target="_blank">[25]</a>
</p>
</div>
<!-- High Concurrency Performance -->
<div class="bg-white p-6 rounded-lg shadow-md mb-6">
<h4 class="text-xl font-semibold mb-4">高并发场景下的性能表现</h4>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="text-center">
<div class="text-3xl font-bold text-green-600 mb-2">46,000 QPS</div>
<div class="text-sm text-gray-600">Lettuce @ 100 线程</div>
<div class="text-xs text-gray-500 mt-1">性能衰减极小</div>
</div>
<div class="text-center">
<div class="text-3xl font-bold text-red-600 mb-2">32,000 QPS</div>
<div class="text-sm text-gray-600">Jedis @ 100 线程</div>
<div class="text-xs text-gray-500 mt-1">性能急剧下降</div>
</div>
</div>
<p class="text-sm text-gray-600 mt-4">
数据来源:<a href="https://www.cnblogs.com/Chary/articles/19121235" class="citation" target="_blank">[46]</a>
</p>
</div>
</div>
</div>
</section>
<div class="section-divider"></div>
<!-- Features and API -->
<section id="features-api" class="py-16 px-8">
<div class="max-w-6xl mx-auto">
<h2 class="text-4xl font-bold text-gray-900 mb-8 serif-italic">功能特性与API详解</h2>
<!-- API Support -->
<div id="api-support" class="mb-16">
<h3 class="text-2xl font-semibold text-gray-900 mb-6">多样化的API支持</h3>
<p class="text-gray-700 mb-8">
Lettuce 提供了三种不同编程模型的 API,以适应从传统同步编程到现代响应式编程的各种需求。
<a href="https://blog.csdn.net/weixin_62320071/article/details/126688061" class="citation" target="_blank">[40]</a>
</p>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8 mb-8">
<!-- Sync API -->
<div class="bg-white p-6 rounded-lg shadow-md border-t-4 border-blue-500">
<div class="flex items-center mb-4">
<i class="fas fa-sync-alt text-blue-500 text-2xl mr-3"></i>
<h4 class="text-xl font-semibold">同步API</h4>
</div>
<p class="text-gray-600 mb-4">最基础、最直观的使用方式,方法调用会阻塞当前线程直到返回结果。</p>
<div class="code-block text-sm">
<pre><code>RedisCommands<String, String> sync = connection.sync();
String value = sync.get("key");</code></pre>
</div>
</div>
<!-- Async API -->
<div class="bg-white p-6 rounded-lg shadow-md border-t-4 border-green-500">
<div class="flex items-center mb-4">
<i class="fas fa-bolt text-green-500 text-2xl mr-3"></i>
<h4 class="text-xl font-semibold">异步API</h4>
</div>
<p class="text-gray-600 mb-4">立即返回 RedisFuture 对象,不会阻塞当前线程,支持回调处理。</p>
<div class="code-block text-sm">
<pre><code>RedisAsyncCommands<String, String> async = connection.async();
RedisFuture<String> future = async.get("key");
future.thenAccept(System.out::println);</code></pre>
</div>
</div>
<!-- Reactive API -->
<div class="bg-white p-6 rounded-lg shadow-md border-t-4 border-purple-500">
<div class="flex items-center mb-4">
<i class="fas fa-stream text-purple-500 text-2xl mr-3"></i>
<h4 class="text-xl font-semibold">响应式API</h4>
</div>
<p class="text-gray-600 mb-4">基于 Project Reactor,返回 Mono 或 Flux,支持流式处理。</p>
<div class="code-block text-sm">
<pre><code>RedisReactiveCommands<String, String> reactive = connection.reactive();
Mono<String> mono = reactive.get("key");
mono.subscribe(System.out::println);</code></pre>
</div>
</div>
</div>
<!-- Reactive Programming Benefits -->
<div class="bg-gradient-to-r from-purple-50 to-pink-50 p-8 rounded-lg">
<h4 class="text-xl font-semibold text-purple-900 mb-4">
<i class="fas fa-star mr-2"></i>响应式编程的优势
</h4>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<h5 class="font-semibold text-purple-800 mb-2">背压支持</h5>
<p class="text-purple-700 text-sm">下游消费者可以控制上游生产者的数据流速,防止系统过载</p>
</div>
<div>
<h5 class="font-semibold text-purple-800 mb-2">组合操作</h5>
<p class="text-purple-700 text-sm">支持 map、filter、reduce 等函数式操作,代码更简洁</p>
</div>
<div>
<h5 class="font-semibold text-purple-800 mb-2">错误处理</h5>
<p class="text-purple-700 text-sm">提供丰富的错误处理机制,如 onErrorResume、retry 等</p>
</div>
<div>
<h5 class="font-semibold text-purple-800 mb-2">Spring 集成</h5>
<p class="text-purple-700 text-sm">与 Spring WebFlux 无缝集成,构建端到端的响应式应用</p>
</div>
</div>
</div>
</div>
<!-- Advanced Features -->
<div id="advanced-features" class="mb-16">
<h3 class="text-2xl font-semibold text-gray-900 mb-6">高级功能特性</h3>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<!-- Auto Reconnect -->
<div class="bg-white p-6 rounded-lg shadow-md">
<h4 class="text-lg font-semibold mb-4 flex items-center">
<i class="fas fa-refresh text-blue-500 mr-2"></i>自动重连与拓扑刷新
</h4>
<p class="text-gray-600 mb-4">
内置强大的自动重连机制,支持配置重连策略。对于 Redis 集群,提供自动拓扑刷新功能。
<a href="https://support.huaweicloud.com/usermanual-dcs/dcs-ug-211105002.html" class="citation" target="_blank">[1]</a>
</p>
<div class="code-block text-sm">
<pre><code>ClusterTopologyRefreshOptions refreshOptions = ClusterTopologyRefreshOptions.builder()
.enablePeriodicRefresh(Duration.ofSeconds(60))
.enableAllAdaptiveRefreshTriggers()
.build();</code></pre>
</div>
</div>
<!-- Cluster Support -->
<div class="bg-white p-6 rounded-lg shadow-md">
<h4 class="text-lg font-semibold mb-4 flex items-center">
<i class="fas fa-sitemap text-green-500 mr-2"></i>Redis集群与哨兵支持
</h4>
<p class="text-gray-600 mb-4">
对 Redis 集群和哨兵模式提供开箱即用的支持,自动处理节点发现和故障转移。
<a href="https://zhuanlan.zhihu.com/p/388041321" class="citation" target="_blank">[54]</a>
</p>
<div class="code-block text-sm">
<pre><code>// 集群模式
RedisClusterClient clusterClient = RedisClusterClient.create(
Arrays.asList("redis://node1:6379", "redis://node2:6379")
);
// 哨兵模式
RedisURI sentinelUri = RedisURI.create(
"redis-sentinel://host1:port1,host2:port2/database#sentinelMasterId"
);</code></pre>
</div>
</div>
<!-- SSL/TLS -->
<div class="bg-white p-6 rounded-lg shadow-md">
<h4 class="text-lg font-semibold mb-4 flex items-center">
<i class="fas fa-lock text-purple-500 mr-2"></i>SSL/TLS加密连接
</h4>
<p class="text-gray-600 mb-4">
支持通过 SSL/TLS 对客户端与 Redis 服务器之间的通信进行加密,满足生产环境安全要求。
</p>
<div class="code-block text-sm">
<pre><code>RedisURI redisUri = RedisURI.builder()
.withHost("localhost")
.withPort(6379)
.withSsl(true) // 启用 SSL
.withVerifyPeer(true) // 验证对等方
.build();</code></pre>
</div>
</div>
<!-- Advanced Data Types -->
<div class="bg-white p-6 rounded-lg shadow-md">
<h4 class="text-lg font-semibold mb-4 flex items-center">
<i class="fas fa-database text-orange-500 mr-2"></i>高级数据类型支持
</h4>
<p class="text-gray-600 mb-4">
支持 Redis 的高级数据类型,如 Streams、GEO、HyperLogLog 等,满足复杂业务场景需求。
</p>
<div class="bg-gray-100 p-3 rounded text-sm">
<code>
// Redis Streams 操作<br>
RedisCommands<String, String> commands = connection.sync();<br>
commands.xadd("stream", "field", "value");
</code>
</div>
</div>
</div>
</div>
</div>
</section>
<div class="section-divider"></div>
<!-- Usage Demos -->
<section id="usage-demos" class="py-16 px-8 bg-gray-50">
<div class="max-w-6xl mx-auto">
<h2 class="text-4xl font-bold text-gray-900 mb-8 serif-italic">使用Demo与最佳实践</h2>
<!-- Environment Setup -->
<div id="environment-setup" class="mb-16">
<h3 class="text-2xl font-semibold text-gray-900 mb-6">环境准备与依赖引入</h3>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-8">
<div>
<h4 class="text-lg font-semibold mb-4 text-blue-600">Maven 依赖配置</h4>
<div class="code-block">
<pre><code><!-- Lettuce 核心依赖 -->
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>6.3.2.RELEASE</version>
</dependency>
<!-- Spring Boot Starter (可选) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency></code></pre>
</div>
</div>
<div>
<h4 class="text-lg font-semibold mb-4 text-green-600">Docker 快速启动</h4>
<div class="code-block">
<pre><code># 启动单机 Redis
docker run -d --name redis-single \
-p 6379:6379 redis:latest
# 启动 Redis 集群(使用 docker-compose)
# 查看官方文档获取详细配置</code></pre>
</div>
<div class="bg-blue-50 p-4 rounded-lg mt-4">
<h5 class="font-semibold text-blue-900 mb-2">开发环境建议</h5>
<ul class="text-blue-800 text-sm list-disc list-inside">
<li>Java 8+</li>
<li>Maven 3.6+ 或 Gradle 6+</li>
<li>Redis 5.0+</li>
<li>Spring Boot 2.4+(可选)</li>
</ul>
</div>
</div>
</div>
</div>
<!-- Single Instance -->
<div id="single-instance" class="mb-16">
<h3 class="text-2xl font-semibold text-gray-900 mb-6">连接Redis单机实例</h3>
<!-- Connection Creation -->
<div class="bg-white p-6 rounded-lg shadow-md mb-8">
<h4 class="text-lg font-semibold mb-4">创建 RedisClient 与连接</h4>
<div class="code-block mb-4">
<pre><code>import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisURI;
import io.lettuce.core.api.StatefulRedisConnection;
import java.time.Duration;
public class LettuceConnectionExample {
public static void main(String[] args) {
// 使用 RedisURI Builder (推荐)
RedisURI redisUri = RedisURI.builder()
.withHost("localhost")
.withPort(6379)
// .withPassword("your_password") // 如果 Redis 设置了密码
.withDatabase(0)
.withTimeout(Duration.ofSeconds(10))
.build();
RedisClient redisClient = RedisClient.create(redisUri);
// 建立连接
StatefulRedisConnection<String, String> connection = redisClient.connect();
System.out.println("Connected to Redis");
// ... 执行 Redis 命令 ...
// 关闭连接和客户端,释放资源
connection.close();
redisClient.shutdown();
}
}</code></pre>
</div>
<div class="bg-yellow-50 p-4 rounded-lg border-l-4 border-yellow-400">
<p class="text-yellow-800">
<i class="fas fa-exclamation-triangle mr-2"></i>
<strong>重要提示:</strong>使用完连接后,记得关闭连接和客户端以释放资源。推荐使用 try-with-resources 或 Spring 的自动管理功能。
</p>
</div>
</div>
<!-- Sync Operations -->
<div class="bg-white p-6 rounded-lg shadow-md mb-8">
<h4 class="text-lg font-semibold mb-4">同步 API 操作示例</h4>
<div class="code-block">
<pre><code>import io.lettuce.core.api.sync.RedisCommands;
// 获取同步命令接口
RedisCommands<String, String> syncCommands = connection.sync();
// 字符串操作
syncCommands.set("user:1:name", "Alice");
String userName = syncCommands.get("user:1:name");
System.out.println("User name: " + userName);
// 哈希操作
syncCommands.hset("user:1", "age", "30");
syncCommands.hset("user:1", "city", "New York");
Map<String, String> user = syncCommands.hgetall("user:1");
System.out.println("User details: " + user);
// 列表操作
syncCommands.lpush("tasks", "task1", "task2", "task3");
List<String> tasks = syncCommands.lrange("tasks", 0, -1);
System.out.println("Task list: " + tasks);</code></pre>
</div>
</div>
<!-- Async Operations -->
<div class="bg-white p-6 rounded-lg shadow-md">
<h4 class="text-lg font-semibold mb-4">异步 API 操作示例</h4>
<div class="code-block">
<pre><code>import io.lettuce.core.api.async.RedisAsyncCommands;
import io.lettuce.core.RedisFuture;
import java.util.concurrent.CompletableFuture;
// 获取异步命令接口
RedisAsyncCommands<String, String> asyncCommands = connection.async();
// 异步执行多个命令
RedisFuture<String> setFuture = asyncCommands.set("asyncKey", "asyncValue");
RedisFuture<String> getFuture = asyncCommands.get("asyncKey");
// 使用 thenAccept 处理结果
getFuture.thenAccept(value -> {
System.out.println("Async get result: " + value);
});
// 组合多个异步操作
CompletableFuture<Void> combinedFuture = CompletableFuture.allOf(
setFuture.toCompletableFuture(),
getFuture.toCompletableFuture()
);
combinedFuture.thenRun(() -> {
System.out.println("Both set and get operations completed.");
// 在这里可以安全地关闭连接
});</code></pre>
</div>
</div>
</div>
<!-- Cluster Mode -->
<div id="cluster-mode" class="mb-16">
<h3 class="text-2xl font-semibold text-gray-900 mb-6">连接Redis集群</h3>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<div class="bg-white p-6 rounded-lg shadow-md">
<h4 class="text-lg font-semibold mb-4">创建 RedisClusterClient</h4>
<div class="code-block">
<pre><code>import io.lettuce.core.cluster.RedisClusterClient;
import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
import java.util.Arrays;
// 使用 RedisURI 列表创建集群客户端
RedisURI node1 = RedisURI.create("redis://localhost", 7000);
RedisURI node2 = RedisURI.create("redis://localhost", 7001);
RedisURI node3 = RedisURI.create("redis://localhost", 7002);
RedisClusterClient clusterClient = RedisClusterClient.create(
Arrays.asList(node1, node2, node3)
);
// 建立集群连接
StatefulRedisClusterConnection<String, String> connection =
clusterClient.connect();
System.out.println("Connected to Redis Cluster");</code></pre>
</div>
</div>
<div class="bg-white p-6 rounded-lg shadow-md">
<h4 class="text-lg font-semibold mb-4">集群模式下的操作</h4>
<div class="code-block">
<pre><code>import io.lettuce.core.cluster.api.sync.RedisClusterCommands;
// 同步操作
RedisClusterCommands<String, String> syncCommands =
connection.sync();
// Lettuce 会自动处理键到槽的映射
// 以及 MOVED/ASK 重定向
syncCommands.set("foo", "bar");
String value = syncCommands.get("foo");
System.out.println("Cluster get result: " + value);
// 哈希标签确保键在同一个槽
syncCommands.set("user:{123}:name", "Alice");
syncCommands.set("user:{123}:age", "30");</code></pre>
</div>
</div>
</div>
</div>
<!-- Pipelining -->
<div id="pipelining" class="mb-16">
<h3 class="text-2xl font-semibold text-gray-900 mb-6">管道(Pipelining)模式使用</h3>
<div class="bg-white p-6 rounded-lg shadow-md mb-8">
<h4 class="text-lg font-semibold mb-4">管道模式的优势与适用场景</h4>
<p class="text-gray-700 mb-4">
管道模式允许客户端一次性发送多个命令,而无需等待每个命令的响应,极大地提高了批量操作的性能。
<a href="http://www.uml.org.cn/sjjm/202304244.asp" class="citation" target="_blank">[22]</a>
</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="bg-blue-50 p-4 rounded-lg">
<h5 class="font-semibold text-blue-900 mb-2">适用场景</h5>
<ul class="text-blue-800 text-sm list-disc list-inside">
<li>批量数据导入</li>
<li>大量键值操作</li>
<li>高延迟网络环境</li>
<li>性能敏感的应用</li>
</ul>
</div>
<div class="bg-green-50 p-4 rounded-lg">
<h5 class="font-semibold text-green-900 mb-2">性能提升</h5>
<ul class="text-green-800 text-sm list-disc list-inside">
<li>减少网络往返时间</li>
<li>提高吞吐量 5-10 倍</li>
<li>降低 CPU 消耗</li>
<li>优化带宽利用</li>
</ul>
</div>
</div>
</div>
<!-- Pipelining Implementation -->
<div class="bg-white p-6 rounded-lg shadow-md">
<h4 class="text-lg font-semibold mb-4">异步 API 实现管道操作</h4>
<div class="code-block">
<pre><code>import io.lettuce.core.api.async.RedisAsyncCommands;
import io.lettuce.core.RedisFuture;
import java.util.List;
import java.util.ArrayList;
// 获取异步命令接口
RedisAsyncCommands<String, String> asyncCommands = connection.async();
// 禁用自动刷新,手动控制命令的发送
asyncCommands.setAutoFlushCommands(false);
List<RedisFuture<?>> futures = new ArrayList<>();
// 批量发送多个命令
for (int i = 0; i < 1000; i++) {
futures.add(asyncCommands.set("key:" + i, "value:" + i));
}
// 手动刷新缓冲区,将所有命令一次性发送给 Redis
asyncCommands.flushCommands();
// 等待所有操作完成
for (RedisFuture<?> future : futures) {
future.get(); // 这里会阻塞等待单个操作完成
}
System.out.println("Pipelined 1000 set operations completed.");
// 重新启用自动刷新
asyncCommands.setAutoFlushCommands(true);</code></pre>
</div>
<div class="bg-yellow-50 p-4 rounded-lg border-l-4 border-yellow-400 mt-4">
<h5 class="font-semibold text-yellow-800 mb-2">最佳实践</h5>
<ul class="text-yellow-700 text-sm list-disc list-inside">
<li>合理控制批量大小,避免一次发送过多命令</li>
<li>考虑使用 CompletableFuture.allOf() 等待所有操作完成</li>
<li>在 finally 块中重新启用自动刷新</li>
<li>监控网络带宽和 Redis 服务器负载</li>
</ul>
</div>
</div>
</div>
</div>
</section>
<div class="section-divider"></div>
<!-- Comparison Analysis -->
<section id="comparison" class="py-16 px-8">
<div class="max-w-6xl mx-auto">
<h2 class="text-4xl font-bold text-gray-900 mb-8 serif-italic">对比分析:Lettuce vs. Jedis</h2>
<!-- Performance Comparison -->
<div id="performance-comparison" class="mb-16">
<h3 class="text-2xl font-semibold text-gray-900 mb-6">性能对比</h3>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-8">
<div class="bg-white p-6 rounded-lg shadow-md">
<h4 class="text-lg font-semibold mb-4 text-red-600">Jedis 性能特点</h4>
<div class="space-y-3">
<div class="flex items-center">
<i class="fas fa-minus-circle text-red-500 mr-2"></i>
<span class="text-sm">阻塞 I/O (BIO) 模型</span>
</div>
<div class="flex items-center">
<i class="fas fa-minus-circle text-red-500 mr-2"></i>
<span class="text-sm">依赖连接池管理</span>
</div>
<div class="flex items-center">
<i class="fas fa-minus-circle text-red-500 mr-2"></i>
<span class="text-sm">高并发下性能衰减明显</span>
</div>
<div class="flex items-center">
<i class="fas fa-minus-circle text-red-500 mr-2"></i>
<span class="text-sm">上下文切换开销大</span>
</div>
</div>
<div class="mt-4 p-3 bg-red-50 rounded">
<div class="text-2xl font-bold text-red-600">32,000</div>
<div class="text-sm text-red-700">QPS @ 100 线程</div>
</div>
</div>
<div class="bg-white p-6 rounded-lg shadow-md">
<h4 class="text-lg font-semibold mb-4 text-green-600">Lettuce 性能特点</h4>
<div class="space-y-3">
<div class="flex items-center">
<i class="fas fa-check-circle text-green-500 mr-2"></i>
<span class="text-sm">非阻塞 I/O (NIO) 模型</span>
</div>
<div class="flex items-center">
<i class="fas fa-check-circle text-green-500 mr-2"></i>
<span class="text-sm">单连接多路复用</span>
</div>
<div class="flex items-center">
<i class="fas fa-check-circle text-green-500 mr-2"></i>
<span class="text-sm">高并发下性能稳定</span>
</div>
<div class="flex items-center">
<i class="fas fa-check-circle text-green-500 mr-2"></i>
<span class="text-sm">资源利用率高</span>
</div>
</div>
<div class="mt-4 p-3 bg-green-50 rounded">
<div class="text-2xl font-bold text-green-600">46,000</div>
<div class="text-sm text-green-700">QPS @ 100 线程</div>
</div>
</div>
</div>
<div class="bg-white p-6 rounded-lg shadow-md">
<h4 class="text-lg font-semibold mb-4">性能对比数据</h4>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="bg-gray-100">
<th class="p-3 text-left">客户端</th>
<th class="p-3 text-left">I/O 模型</th>
<th class="p-3 text-left">连接管理</th>
<th class="p-3 text-left">10 线程 QPS</th>
<th class="p-3 text-left">100 线程 QPS</th>
<th class="p-3 text-left">内存占用</th>
</tr>
</thead>
<tbody>
<tr class="border-b">
<td class="p-3 font-semibold text-red-600">Jedis</td>
<td class="p-3">阻塞 I/O (BIO)</td>
<td class="p-3">连接池</td>
<td class="p-3">45,000</td>
<td class="p-3 text-red-600">32,000 (-29%)</td>
<td class="p-3">120MB (100 连接)</td>
</tr>
<tr>
<td class="p-3 font-semibold text-green-600">Lettuce</td>
<td class="p-3">非阻塞 I/O (NIO)</td>
<td class="p-3">单连接多路复用</td>
<td class="p-3">48,000</td>
<td class="p-3 text-green-600">46,000 (-4%)</td>
<td class="p-3">80MB (100 连接)</td>
</tr>
</tbody>
</table>
</div>
<p class="text-sm text-gray-600 mt-3">
数据来源:<a href="https://www.cnblogs.com/Chary/articles/19121235" class="citation" target="_blank">[46]</a>
</p>
</div>
</div>
<!-- Features Comparison -->
<div id="features-comparison" class="mb-16">
<h3 class="text-2xl font-semibold text-gray-900 mb-6">功能与易用性对比</h3>
<div class="bg-white p-6 rounded-lg shadow-md mb-8">
<h4 class="text-lg font-semibold mb-4">功能特性对比</h4>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<h5 class="font-semibold text-blue-600 mb-3">API 设计</h5>
<div class="space-y-2">
<div class="flex justify-between items-center">
<span class="text-sm">同步 API</span>
<div>
<span class="text-green-600">✓</span>
<span class="text-green-600">✓</span>
</div>
</div>
<div class="flex justify-between items-center">
<span class="text-sm">异步 API</span>
<div>
<span class="text-red-600">✗</span>
<span class="text-green-600">✓</span>
</div>
</div>
<div class="flex justify-between items-center">
<span class="text-sm">响应式 API</span>
<div>
<span class="text-red-600">✗</span>
<span class="text-green-600">✓</span>
</div>
</div>
</div>
</div>
<div>
<h5 class="font-semibold text-purple-600 mb-3">高级功能</h5>
<div class="space-y-2">
<div class="flex justify-between items-center">
<span class="text-sm">Redis 集群</span>
<div>
<span class="text-green-600">✓</span>
<span class="text-green-600">✓</span>
</div>
</div>
<div class="flex justify-between items-center">
<span class="text-sm">哨兵模式</span>
<div>
<span class="text-green-600">✓</span>
<span class="text-green-600">✓</span>
</div>
</div>
<div class="flex justify-between items-center">
<span class="text-sm">SSL/TLS 加密</span>
<div>
<span class="text-yellow-600">△</span>
<span class="text-green-600">✓</span>
</div>
</div>
<div class="flex justify-between items-center">
<span class="text-sm">自动重连</span>
<div>
<span class="text-yellow-600">△</span>
<span class="text-green-600">✓</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Learning Curve -->
<div class="bg-gradient-to-r from-blue-50 to-indigo-50 p-6 rounded-lg">
<h4 class="text-lg font-semibold text-blue-900 mb-4">学习曲线对比</h4>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="bg-white p-4 rounded-lg shadow-sm">
<h5 class="font-semibold text-red-700 mb-2">Jedis</h5>
<div class="flex items-center mb-2">
<div class="w-full bg-gray-200 rounded-full h-2 mr-2">
<div class="bg-green-500 h-2 rounded-full" style="width: 30%"></div>
</div>
<span class="text-sm">简单</span>
</div>
<p class="text-sm text-gray-600">API 直观,方法名与 Redis 命令一一对应,上手快</p>
</div>
<div class="bg-white p-4 rounded-lg shadow-sm">
<h5 class="font-semibold text-blue-700 mb-2">Lettuce</h5>
<div class="flex items-center mb-2">
<div class="w-full bg-gray-200 rounded-full h-2 mr-2">
<div class="bg-yellow-500 h-2 rounded-full" style="width: 60%"></div>
</div>
<span class="text-sm">中等</span>
</div>
<p class="text-sm text-gray-600">API 灵活但需要理解异步/响应式编程概念</p>
</div>
</div>
</div>
</div>
<!-- Scenario Analysis -->
<div id="scenario-analysis" class="mb-16">
<h3 class="text-2xl font-semibold text-gray-900 mb-6">适用场景与选型建议</h3>
<!-- Scenario Matrix -->
<div class="bg-white p-6 rounded-lg shadow-md mb-8">
<h4 class="text-lg font-semibold mb-4">场景适用性矩阵</h4>
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="bg-gray-100">
<th class="p-3 text-left">应用场景</th>
<th class="p-3 text-center">Jedis</th>
<th class="p-3 text-center">Lettuce</th>
<th class="p-3 text-left">推荐理由</th>
</tr>
</thead>
<tbody>
<tr class="border-b">
<td class="p-3 font-medium">简单应用/原型</td>
<td class="p-3 text-center">
<span class="inline-block w-3 h-3 bg-green-500 rounded-full"></span>
</td>
<td class="p-3 text-center">
<span class="inline-block w-3 h-3 bg-yellow-500 rounded-full"></span>
</td>
<td class="p-3 text-xs">Jedis 简单直观,快速上手</td>
</tr>
<tr class="border-b">
<td class="p-3 font-medium">高并发微服务</td>
<td class="p-3 text-center">
<span class="inline-block w-3 h-3 bg-red-500 rounded-full"></span>
</td>
<td class="p-3 text-center">
<span class="inline-block w-3 h-3 bg-green-500 rounded-full"></span>
</td>
<td class="p-3 text-xs">Lettuce 异步非阻塞,性能卓越</td>
</tr>
<tr class="border-b">
<td class="p-3 font-medium">响应式架构</td>
<td class="p-3 text-center">
<span class="inline-block w-3 h-3 bg-red-500 rounded-full"></span>
</td>
<td class="p-3 text-center">
<span class="inline-block w-3 h-3 bg-green-500 rounded-full"></span>
</td>
<td class="p-3 text-xs">Lettuce 原生响应式支持</td>
</tr>
<tr class="border-b">
<td class="p-3 font-medium">云原生环境</td>
<td class="p-3 text-center">
<span class="inline-block w-3 h-3 bg-red-500 rounded-full"></span>
</td>
<td class="p-3 text-center">
<span class="inline-block w-3 h-3 bg-green-500 rounded-full"></span>
</td>
<td class="p-3 text-xs">Lettuce 资源消耗低,适合容器</td>
</tr>
<tr>
<td class="p-3 font-medium">现有项目维护</td>
<td class="p-3 text-center">
<span class="inline-block w-3 h-3 bg-green-500 rounded-full"></span>
</td>
<td class="p-3 text-center">
<span class="inline-block w-3 h-3 bg-yellow-500 rounded-full"></span>
</td>
<td class="p-3 text-xs">如无性能问题,可继续使用 Jedis</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Final Recommendation -->
<div class="bg-gradient-to-r from-green-50 to-blue-50 p-8 rounded-lg border-l-4 border-green-500">
<h4 class="text-xl font-semibold text-green-900 mb-4">
<i class="fas fa-thumbs-up mr-2"></i>官方推荐
</h4>
<p class="text-green-800 mb-4 text-lg">
<strong>一句话总结:对于现代 Java 应用,特别是基于 Spring Boot 的项目,Lettuce 是更推荐的默认选择。</strong>
</p>
<p class="text-green-700 mb-4">
自 Spring Boot 2.x 起,官方已经将默认的 Redis 客户端从 Jedis 切换为 Lettuce,这本身就说明了社区和官方对 Lettuce 的认可和推荐。
<a href="https://github.com/yulewei/redis-client-benchmark" class="citation" target="_blank">[23]</a>
</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="bg-white p-4 rounded-lg shadow-sm">
<h5 class="font-semibold text-green-800 mb-2">Lettuce 优势</h5>
<ul class="text-green-700 text-sm list-disc list-inside">
<li>性能更优,高并发下表现稳定</li>
<li>支持异步和响应式编程</li>
<li>线程安全,无需连接池管理</li>
<li>资源消耗低,适合云原生环境</li>
<li>企业级特性支持完善</li>
</ul>
</div>
<div class="bg-white p-4 rounded-lg shadow-sm">
<h5 class="font-semibold text-yellow-800 mb-2">需要考虑</h5>
<ul class="text-yellow-700 text-sm list-disc list-inside">
<li>学习曲线略陡</li>
<li>需要理解异步编程概念</li>
<li>调试相对复杂</li>
<li>迁移成本(现有项目)</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
<script>
// Initialize Mermaid with enhanced configuration
mermaid.initialize({
startOnLoad: true,
theme: 'base',
themeVariables: {
// Primary colors with good contrast
primaryColor: '#dbeafe',
primaryTextColor: '#1e293b',
primaryBorderColor: '#2563eb',
// Secondary colors
secondaryColor: '#dcfce7',
secondaryTextColor: '#1e293b',
secondaryBorderColor: '#16a34a',
// Tertiary colors
tertiaryColor: '#fef3c7',
tertiaryTextColor: '#1e293b',
tertiaryBorderColor: '#d97706',
// Additional node colors with high contrast
quaternaryColor: '#fce7f3',
quaternaryTextColor: '#1e293b',
quaternaryBorderColor: '#ec4899',
// Background and general styling
background: '#ffffff',
mainBkg: '#f8fafc',
secondBkg: '#e2e8f0',
tertiaryBkg: '#cbd5e1',
// Lines and connections
lineColor: '#64748b',
edgeLabelBackground: '#ffffff',
// Text styling
textColor: '#1e293b',
fontFamily: 'Inter, sans-serif',
fontSize: '14px',
// Node specific colors for better contrast
cScale0: '#dbeafe',
cScale1: '#dcfce7',
cScale2: '#fef3c7',
cScale3: '#fce7f3',
cScale4: '#f3e8ff',
cScale5: '#ecfdf5',
cScale6: '#fef7cd',
// Ensure all text is dark for readability
nodeBkg: '#f8fafc',
nodeTextColor: '#1e293b'
},
flowchart: {
useMaxWidth: false,
htmlLabels: true,
curve: 'basis',
padding: 20,
nodeSpacing: 50,
rankSpacing: 80
},
// Set reasonable size constraints
maxTextSize: 90000,
maxEdges: 200
});
// Initialize Mermaid Controls for zoom and pan
function initializeMermaidControls() {
const containers = document.querySelectorAll('.mermaid-container');
containers.forEach(container => {
const mermaidElement = container.querySelector('.mermaid');
let scale = 1;
let isDragging = false;
let startX, startY, translateX = 0, translateY = 0;
// 触摸相关状态
let isTouch = false;
let touchStartTime = 0;
let initialDistance = 0;
let initialScale = 1;
let isPinching = false;
// Zoom controls
const zoomInBtn = container.querySelector('.zoom-in');
const zoomOutBtn = container.querySelector('.zoom-out');
const resetBtn = container.querySelector('.reset-zoom');
const fullscreenBtn = container.querySelector('.fullscreen');
function updateTransform() {
mermaidElement.style.transform = `translate(${translateX}px, ${translateY}px) scale(${scale})`;
if (scale > 1) {
container.classList.add('zoomed');
} else {
container.classList.remove('zoomed');
}
mermaidElement.style.cursor = isDragging ? 'grabbing' : 'grab';
}
if (zoomInBtn) {
zoomInBtn.addEventListener('click', () => {
scale = Math.min(scale * 1.25, 4);
updateTransform();
});
}
if (zoomOutBtn) {
zoomOutBtn.addEventListener('click', () => {
scale = Math.max(scale / 1.25, 0.3);
if (scale <= 1) {
translateX = 0;
translateY = 0;
}
updateTransform();
});
}
if (resetBtn) {
resetBtn.addEventListener('click', () => {
scale = 1;
translateX = 0;
translateY = 0;
updateTransform();
});
}
if (fullscreenBtn) {
fullscreenBtn.addEventListener('click', () => {
if (container.requestFullscreen) {
container.requestFullscreen();
} else if (container.webkitRequestFullscreen) {
container.webkitRequestFullscreen();
} else if (container.msRequestFullscreen) {
container.msRequestFullscreen();
}
});
}
// Mouse Events
mermaidElement.addEventListener('mousedown', (e) => {
if (isTouch) return; // 如果是触摸设备,忽略鼠标事件
isDragging = true;
startX = e.clientX - translateX;
startY = e.clientY - translateY;
mermaidElement.style.cursor = 'grabbing';
updateTransform();
e.preventDefault();
});
document.addEventListener('mousemove', (e) => {
if (isDragging && !isTouch) {
translateX = e.clientX - startX;
translateY = e.clientY - startY;
updateTransform();
}
});
document.addEventListener('mouseup', () => {
if (isDragging && !isTouch) {
isDragging = false;
mermaidElement.style.cursor = 'grab';
updateTransform();
}
});
document.addEventListener('mouseleave', () => {
if (isDragging && !isTouch) {
isDragging = false;
mermaidElement.style.cursor = 'grab';
updateTransform();
}
});
// 获取两点之间的距离
function getTouchDistance(touch1, touch2) {
return Math.hypot(
touch2.clientX - touch1.clientX,
touch2.clientY - touch1.clientY
);
}
// Touch Events - 触摸事件处理
mermaidElement.addEventListener('touchstart', (e) => {
isTouch = true;
touchStartTime = Date.now();
if (e.touches.length === 1) {
// 单指拖动
isPinching = false;
isDragging = true;
const touch = e.touches[0];
startX = touch.clientX - translateX;
startY = touch.clientY - translateY;
} else if (e.touches.length === 2) {
// 双指缩放
isPinching = true;
isDragging = false;
const touch1 = e.touches[0];
const touch2 = e.touches[1];
initialDistance = getTouchDistance(touch1, touch2);
initialScale = scale;
}
e.preventDefault();
}, { passive: false });
mermaidElement.addEventListener('touchmove', (e) => {
if (e.touches.length === 1 && isDragging && !isPinching) {
// 单指拖动
const touch = e.touches[0];
translateX = touch.clientX - startX;
translateY = touch.clientY - startY;
updateTransform();
} else if (e.touches.length === 2 && isPinching) {
// 双指缩放
const touch1 = e.touches[0];
const touch2 = e.touches[1];
const currentDistance = getTouchDistance(touch1, touch2);
if (initialDistance > 0) {
const newScale = Math.min(Math.max(
initialScale * (currentDistance / initialDistance),
0.3
), 4);
scale = newScale;
updateTransform();
}
}
e.preventDefault();
}, { passive: false });
mermaidElement.addEventListener('touchend', (e) => {
// 重置状态
if (e.touches.length === 0) {
isDragging = false;
isPinching = false;
initialDistance = 0;
// 延迟重置isTouch,避免鼠标事件立即触发
setTimeout(() => {
isTouch = false;
}, 100);
} else if (e.touches.length === 1 && isPinching) {
// 从双指变为单指,切换为拖动模式
isPinching = false;
isDragging = true;
const touch = e.touches[0];
startX = touch.clientX - translateX;
startY = touch.clientY - translateY;
}
updateTransform();
});
mermaidElement.addEventListener('touchcancel', (e) => {
isDragging = false;
isPinching = false;
initialDistance = 0;
setTimeout(() => {
isTouch = false;
}, 100);
updateTransform();
});
// Enhanced wheel zoom with better center point handling
container.addEventListener('wheel', (e) => {
e.preventDefault();
const rect = container.getBoundingClientRect();
const centerX = rect.width / 2;
const centerY = rect.height / 2;
const delta = e.deltaY > 0 ? 0.9 : 1.1;
const newScale = Math.min(Math.max(scale * delta, 0.3), 4);
// Adjust translation to zoom towards center
if (newScale !== scale) {
const scaleDiff = newScale / scale;
translateX = translateX * scaleDiff;
translateY = translateY * scaleDiff;
scale = newScale;
if (scale <= 1) {
translateX = 0;
translateY = 0;
}
updateTransform();
}
});
// Initialize display
updateTransform();
});
}
// Initialize mermaid controls when page loads
document.addEventListener('DOMContentLoaded', function() {
// Initialize mermaid controls when DOM is loaded
setTimeout(() => {
initializeMermaidControls();
}, 1000);
// Smooth scrolling for TOC links
document.querySelectorAll('.toc-item').forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
const targetId = this.getAttribute('href').substring(1);
const targetElement = document.getElementById(targetId);
if (targetElement) {
targetElement.scrollIntoView({ behavior: 'smooth' });
}
});
});
// Highlight active section in TOC
window.addEventListener('scroll', function() {
const sections = document.querySelectorAll('section[id], div[id]');
const tocLinks = document.querySelectorAll('.toc-item');
let currentSection = '';
sections.forEach(section => {
const rect = section.getBoundingClientRect();
if (rect.top <= 100 && rect.bottom >= 100) {
currentSection = section.id;
}
});
tocLinks.forEach(link => {
link.classList.remove('text-blue-600', 'border-blue-600', 'bg-blue-50');
if (link.getAttribute('href') === '#' + currentSection) {
link.classList.add('text-blue-600', 'border-blue-600', 'bg-blue-50');
}
});
});
});
</script>
</body>
</html>
登录后可参与表态
讨论回复
1 条回复
QianXun (QianXun)
#1
10-15 05:06
登录后可参与表态