一、NoSQL 與 Redis 速覽
1.1 NoSQL 四大分類
| 類型 | 代表產品 | 特點 |
| 鍵值 | Redis, Voldemort, Oracle BDB | 高性能、簡單、適合緩存 |
| 列存儲 | Cassandra, HBase, Riak | 海量分布式存儲、列族組織 |
| 文檔 | MongoDB, CouchDB, SequoiaDB | 半結構化、JSON、支持嵌套查詢 |
| 圖形 | Neo4J, InfoGrid | 關係圖譜、社交網絡、推薦系統 |
1.2 Redis 定位
- ANSI C 開發、BSD 協議、基於內存+可持久化的 Key-Value 存儲。
- 數據結構豐富:String、Hash、List、Set、Sorted Set、Bitmap、HyperLogLog、Geospatial、Stream。
- 單線程模型、IO 多路復用、高性能(10萬+ QPS)。
二、Windows 下 Redis 安裝與服務化
2.1 下載與解壓
2.2 註冊為 Windows 服務
# 管理員 CMD 執行
cd D:\Redis
redis-server --service-install redis.windows.conf --loglevel verbose
redis-server --service-start
2.3 批處理腳本管理多服務(含 Redis)
@echo off
:a
echo 請選擇操作:
echo 1 啟動 MSSQL 2 停止 MSSQL
echo 3 啟動 Oracle 4 停止 Oracle
echo 5 快速關機
echo 6 啟動 MySQL 7 停止 MySQL
echo 8 啟動 Redis 9 停止 Redis
set /p var1=請輸入指令 [1-9]:
if "%var1%"=="8" net start redis
if "%var1%"=="9" net stop redis
... 其他服務同理 ...
goto a

三、Jedis 客戶端實戰
3.1 Maven 依賴
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.3.1</version> <!-- 當前建議 4.x,兼容 Redis 6+ -->
</dependency>

3.2 基礎連接與 CRUD
public class HelloJedis {
public static void main(String[] args) {
// 1. 創建連接(生產環境請用連接池 JedisPool)
try (Jedis jedis = new Jedis("127.0.0.1", 6379)) {
// 2. String 操作
jedis.set("message", "Hello Redis!");
System.out.println(jedis.get("message"));
// 3. Hash 操作
jedis.hset("user:1", "name", "張三");
jedis.hset("user:1", "age", "25");
System.out.println(jedis.hgetAll("user:1"));
// 4. List 操作
jedis.lpush("tasks", "task1", "task2");
System.out.println(jedis.lrange("tasks", 0, -1));
// 5. 過期時間
jedis.expire("message", 60); // 60秒後過期
}
}
}

3.3 生產必備:JedisPool 配置
@Configuration
public class RedisConfig {
@Bean
public JedisPool jedisPool(@Value("${redis.host}") String host,
@Value("${redis.port}") int port) {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(50);
config.setMaxIdle(20);
config.setMinIdle(5);
config.setTestOnBorrow(true);
return new JedisPool(config, host, port, 3000);
}
}
四、Redis 持久化機制深度解析
4.1 RDB(快照)
- 觸發條件(默認配置):
- 900秒內 ≥1 key 變化
- 300秒內 ≥10 key 變化
- 60秒內 ≥10000 key 變化
- 優勢:單文件、備份易、災難恢復快、fork 子進程不阻塞主進程、大數據集啟動快。
- 劣勢:定時快照間隔內數據可能丟失、fork 瞬間大內存佔用可能卡頓。
4.2 AOF(日志追加)
- 記錄每條寫命令,重放重建數據。
- 三種同步策略:
always:每寫入同步(最安全、最慢)。
everysec:每秒同步(默認、平衡)。
no:交給 OS,不保證(最快、可能丟數據)。
- 優勢:數據安全性高、append-only 不易損壞、支持 rewrite 壓縮、日志可讀可人工修復。
- 劣勢:文件體積大、恢復慢、everysec 下仍可能丟 1 秒數據。
4.3 混合持久化(Redis 4.0+)
aof-use-rdb-preamble yes:AOF 文件前綴 RDB 快照,後綴增量命令,兼顧啟動速度與數據安全。
4.4 手動觸發持久化 API
// 同步阻塞保存(慎用,阻塞主線程)
jedis.save();
// 異步非阻塞保存(推薦)
jedis.bgsave();

五、綜合案例:汽車管理系統(序列化存儲)
5.1 實體類
@Data @AllArgsConstructor @NoArgsConstructor
public class Car implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
private double speed;
}
5.2 序列化工具類
public class SerializeUtil {
public static byte[] serialize(Object obj) {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
oos.writeObject(obj);
return baos.toByteArray();
} catch (IOException e) { throw new RuntimeException(e); }
}
@SuppressWarnings("unchecked")
public static <T> T deserialize(byte[] bytes, Class<T> clazz) {
try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais)) {
return (T) ois.readObject();
} catch (IOException | ClassNotFoundException e) { throw new RuntimeException(e); }
}
}
5.3 DAO 層封裝
public class CarDAO {
private static final String KEY = "cars";
private List<Car> cars = new ArrayList<>();
public CarDAO() { load(); }
public void save() {
try (Jedis jedis = new Jedis("127.0.0.1", 6379)) {
jedis.set(KEY.getBytes(), SerializeUtil.serialize(cars));
jedis.bgsave();
}
}
public void load() {
try (Jedis jedis = new Jedis("127.0.0.1", 6379)) {
byte[] data = jedis.get(KEY.getBytes());
if (data != null && data.length > 0) {
cars = SerializeUtil.deserialize(data, new TypeReference<List<Car>>() {});
}
}
}
// CRUD 方法均調用 save() 持久化
public void add(Car car) { cars.add(car); save(); }
public Car getById(int id) { return cars.stream().filter(c -> c.getId() == id).findFirst().orElse(null); }
public void remove(int id) { cars.remove(getById(id)); save(); }
public List<Car> getAll() { return cars; }
public void setAll(List<Car> list) { this.cars = list; save(); }
}
5.4 JUnit 測試
public class CarTest {
static CarDAO dao;
@BeforeClass
public static void init() { dao = new CarDAO(); }
@Test public void testBatchAdd() {
dao.setAll(Arrays.asList(
new Car(1001, "Benz 600", 230),
new Car(1002, "BMW X7+", 200),
new Car(1003, "Audi A8", 180)
));
}
@Test public void testQueryAll() {
dao.getAll().forEach(System.out::println);
}
@Test public void testAddOne() { dao.add(new Car(1004, "BYD F8", 150)); }
@Test public void testGetById() { System.out.println(dao.getById(1001)); }
@Test public void testRemove() { dao.remove(1004); }
}

六、最佳實踐總結
| 場景 | 建議 |
| 緩存 | 純內存、無持久化、TTL 淘汰 |
| 會話存儲 | RDB 每分鐘快照 + AOF everysec |
| 高併發計數器 | INCR 原子操作、無需持久化 |
| 分布式鎖 | SET NX EX + Lua 腳本釋放 |
| 生產部署 | Linux + Redis Cluster + Sentinel + AOF混合持久化 |
七、學習資源