介紹 Redis 是一個開源的記憶體資料庫,它支持多種數據結構,並且常用於高速緩存、會話管理、消息隊列等場景。Redis 的全稱是 Remote Dictionary Server,是一種 key-value(鍵值對)存儲系統,能夠以極高的性能處理大量數據的讀寫操作。 Redis 的主要特點: 基於內 ...
介紹
Redis 是一個開源的記憶體資料庫,它支持多種數據結構,並且常用於高速緩存、會話管理、消息隊列等場景。Redis 的全稱是 Remote Dictionary Server,是一種 key-value(鍵值對)存儲系統,能夠以極高的性能處理大量數據的讀寫操作。
Redis 的主要特點:
- 基於記憶體:數據存儲在記憶體中,具有極高的讀寫速度,適用於實時數據處理和快速響應需求的應用。
- 支持持久化:雖然是記憶體資料庫,但 Redis 提供了將數據保存到磁碟的持久化功能,防止數據丟失。
- 豐富的數據結構
- 數據過期與自動刪除:Redis 支持為每個鍵設置過期時間,到期後自動刪除,常用於緩存系統。
- 發佈/訂閱機制:Redis 提供了消息隊列功能,可以讓客戶端訂閱和發佈消息。
- 事務支持:Redis 支持簡單的事務機制,允許多個命令作為一個原子操作執行。
- 高可用性與分散式:通過 Redis Cluster、Sentinel 機制支持高可用和自動故障轉移,能夠在分散式環境中使用。
1、Redis 基本配置
Redis 的配置文件通常命名為 redis.conf
,存放在 Redis 安裝目錄中。通過修改該文件,可以自定義 Redis 的各種行為。
配置文件位置
-
預設情況下,
redis.conf
文件位於 Redis 安裝目錄中。您可以在啟動 Redis 時指定該文件的位置,例如:redis-server /path/to/redis.conf
關鍵配置選項
1. 埠號
-
port
:指定 Redis 伺服器監聽的埠號。預設埠是6379
。port 6379
2. 綁定地址
-
bind
:指定 Redis 只在特定的網路介面上監聽。如果您希望 Redis 只接受來自本地的連接,可以將其設置為127.0.0.1
。bind 127.0.0.1
3. 守護進程模式
-
daemonize
:指定 Redis 是否以守護進程的方式運行。如果設置為yes
,Redis 將在後臺運行。預設值是no
。daemonize yes
4. 密碼保護
-
requirepass
:為 Redis 設置訪問密碼,只有提供正確密碼的客戶端才能連接到 Redis 伺服器。requirepass yourpassword
5. RDB 快照文件
-
dbfilename
:指定 RDB 快照文件的名稱。預設文件名為dump.rdb
。dbfilename dump.rdb
-
dir
:指定 RDB 快照文件的存放目錄。dir /var/lib/redis/
啟動和使用 Redis 配置
-
修改完
redis.conf
後,您可以通過以下命令啟動 Redis:redis-server /path/to/redis.conf
-
可以通過以下命令檢查 Redis 是否正確載入了配置文件:
redis-cli CONFIG GET *
這會顯示當前 Redis 實例的所有配置選項及其值。
通過這些基本配置,我們可以根據需要自定義 Redis 的行為,以適應不同的應用場景。 -
使用 AUTH 命令進行身份驗證
AUTH your_password
2、Redis 的通用命令
除了與數據結構相關的命令外,Redis 還提供了一些通用命令,用於管理 Redis 實例、數據操作和伺服器配置。
-
鍵管理:
DEL key
:刪除鍵。EXISTS key
:檢查鍵是否存在。EXPIRE key seconds
:為鍵設置過期時間。KEYS pattern
:查找所有符合給定模式的鍵。TTL key
:查看鍵的剩餘生存時間。
DEL mykey EXISTS mykey EXPIRE mykey 60 KEYS *pattern* TTL mykey
3、Redis 的數據結構
Redis 是一個高性能的鍵值存儲系統,支持多種複雜的數據結構。這些數據結構使得 Redis 不僅可以作為簡單的緩存,還能滿足更多樣化的數據存儲需求。以下是 Redis 支持的主要數據結構:
字元串(String )
String 是 Redis 中最基本的數據類型,每個鍵對應一個字元串類型的值(value)。
常見命令
- SET:添加或修改一個鍵值對。例如
SET key value
。 - GET:根據鍵獲取對應的值。例如
GET key
。 - MSET:批量添加多個鍵值對。例如
MSET key1 value1 key2 value2
。 - MGET:根據多個鍵獲取多個值。例如
MGET key1 key2
。 - INCR:讓一個整型的鍵自增1。例如
INCR counter
。 - INCRBY:讓一個整型的鍵自增指定步長。例如
INCRBY counter 5
。 - INCRBYFLOAT:讓一個浮點數的鍵自增指定步長。例如
INCRBYFLOAT balance 0.5
。 - SETNX:添加一個鍵值對,前提是這個鍵不存在,否則不執行。例如
SETNX key value
。 - SETEX:添加一個帶有過期時間的鍵值對。例如
SETEX key 60 value
(60秒後過期)。
哈希(Hash )
Hash 是 Redis 中的一種用於存儲鍵值對的集合。它類似於編程語言中的哈希表或字典。一個 Hash 里可以存儲多個欄位和值,因此非常適合存儲對象。
常見命令
- HSET:向 Hash 中添加一個欄位和值。例如
HSET key field value
。 - HGET:獲取 Hash 中某個欄位的值。例如
HGET key field
。 - HMSET:批量添加多個欄位和值。例如
HMSET key field1 value1 field2 value2
。 - HMGET:批量獲取多個欄位的值。例如
HMGET key field1 field2
。 - HGETALL:獲取 Hash 中所有的欄位和值。例如
HGETALL key
。 - HKEYS:獲取 Hash 中的所有欄位名。例如
HKEYS key
。 - HVALS:獲取 Hash 中的所有值。例如
HVALS key
。 - HINCRBY:讓 Hash 中某個欄位的值自增指定步長。例如
HINCRBY key field 2
。 - HSETNX:向 Hash 中添加一個欄位和值,前提是這個欄位不存在。例如
HSETNX key field value
。
列表(List)
列表是一個有序的字元串集合,可以在集合的頭部或尾部插入、刪除元素。適合用於實現消息隊列等功能。
常見命令
- LPUSH:在列表頭部插入一個元素。例如
LPUSH mylist "world"
。 - RPUSH:在列表尾部插入一個元素。例如
RPUSH mylist "hello"
。 - LPOP:移除並返回列表的第一個元素。例如
LPOP mylist
。 - RPOP:移除並返回列表的最後一個元素。例如
RPOP mylist
。 - LRANGE:獲取列表的一個子集。例如
LRANGE mylist 0 -1
。
集合(Set)
集合是無序的字元串集合,不允許重覆元素。適合用於存儲需要唯一性的集合,如標簽、用戶角色等。
常見命令
- SADD:向集合添加一個元素。例如
SADD myset "apple"
。 - SREM:移除集合中的一個元素。例如
SREM myset "apple"
。 - SCARD:返回集合中元素的個數。例如
SCARD myset
。 - SMEMBERS:獲取集合中的所有元素。例如
SMEMBERS myset
。 - SISMEMBER:判斷元素是否在集合中。例如
SISMEMBER myset "apple"
。
有序集合(Sorted Set)
有序集合類似於集合,但每個元素都會關聯一個分數,元素按分數進行排序。適合用於排名、評分系統等場景。
常見命令
- ZADD:向有序集合添加一個元素,並設置分數。例如
ZADD leaderboard 100 "player1"
。 - ZRANGE:按索引範圍獲取有序集合中的元素,可以選擇同時返回分數。例如
ZRANGE leaderboard 0 -1 WITHSCORES
。 - ZSCORE:獲取有序集合中指定元素的分數。例如
ZSCORE leaderboard "player1"
。 - ZREM:移除有序集合中的一個元素。例如
ZREM leaderboard "player1"
。
Jedis 是一個用於與 Redis 資料庫交互的 Java 客戶端庫。通過 Jedis,你可以在 Java 應用程式中執行各種 Redis 操作,如增刪改查等。Jedis 提供了一組簡單易用的 API,使開發者可以輕鬆地將 Redis 集成到他們的 Java 應用程式中。
" : "的作用
在 Redis 中,冒號 (:
) 用於創建鍵名的層級結構,以幫助組織和管理數據。例如,user:1000:name
表示用戶 ID 為 1000 的名字,order:5000:status
表示訂單 ID 為 5000 的狀態。使用冒號可以讓數據看起來像路徑一樣分層,便於分類和查詢。
假設你在存儲用戶信息和訂單信息:
user:1000:name
->"Alice"
(用戶 ID 為 1000 的名字)user:1000:email
->"[email protected]"
(用戶 ID 為 1000 的電子郵件)order:2000:status
->"shipped"
(訂單 ID 為 2000 的狀態)
這裡,user:
和 order:
是首碼,用於區分不同類型的數據,而冒號 :
用於分隔不同的層級。
4、jedis
Jedis 是一個用於與 Redis 資料庫交互的 Java 客戶端庫。通過 Jedis,你可以在 Java 應用程式中執行各種 Redis 操作,如增刪改查等。Jedis 提供了一組簡單易用的 API,使開發者可以輕鬆地將 Redis 集成到他們的 Java 應用程式中。
Jedis 的基本用法
-
引入依賴
在 Maven 官網獲取 Jedis 依賴,並添加到pom.xml
中:
-
連接 Redis
使用 Jedis 連接 Redis 非常簡單。以下是一個基本的連接示例:import redis.clients.jedis.Jedis; public class RedisExample { public static void main(String[] args) { // 創建一個 Jedis 對象,並指定 Redis 伺服器的地址和埠 Jedis jedis = new Jedis("localhost", 6379); // 輸入密碼,如果沒有修改配置文件修改密碼的話,不用寫這個 jedis.auth(“123456”); // 設置 Redis 字元串數據 jedis.set("mykey", "Hello, Redis!"); // 獲取並列印 Redis 字元串數據 System.out.println("Redis 存儲的字元串: " + jedis.get("mykey")); // 關閉 Jedis 連接 jedis.close(); } }
-
常見操作
Jedis 支持 Redis 的所有基本數據結構和操作。(上面3、Redis 的數據結構
中的命令 jedis 都有對應的方法)- 字元串(String):
jedis.set(key, value)
,jedis.get(key)
- 哈希(Hash):
jedis.hset(key, field, value)
,jedis.hget(key, field)
- 列表(List):
jedis.lpush(key, value)
,jedis.lrange(key, start, end)
- 集合(Set):
jedis.sadd(key, member)
,jedis.smembers(key)
- 有序集合(Sorted Set):
jedis.zadd(key, score, member)
,jedis.zrange(key, start, end)
- 字元串(String):
-
連接池
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class JedisConnectionFactory {
private static final JedisPool jedisPool;
static {
// 配置連接池
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(8); // 最大連接數
poolConfig.setMaxIdle(8); // 最大空閑連接數
poolConfig.setMinIdle(0); // 最小空閑連接數
poolConfig.setMaxWaitMillis(1000); // 最大等待時間
// 創建連接池對象
jedisPool = new JedisPool(poolConfig,
"127.0.0.1", // Redis 主機地址
6379, // Redis 埠號
1000, // 超時時間
"yourPassword"); // Redis 密碼
}
public static Jedis getJedis() { // 通過這個方法在pool中獲取jedis
return jedisPool.getResource();
}
}
參數說明:
config
:JedisPoolConfig
配置對象,用於配置連接池參數。redisHost
: Redis 伺服器的主機地址。redisPort
: Redis 伺服器的埠號。2000
: 連接超時時間,單位為毫秒。redisPassword
: Redis 伺服器的密碼。
5、SpringDataRedis
Spring Data Redis 是 Spring Data 生態系統中的一個模塊,提供與 Redis 的簡便集成。Redis 是一個高性能的記憶體鍵值存儲,Spring Data Redis 通過提供簡單、一致和聲明式的方式,簡化了與 Redis 的交互,將低級別的 Redis 操作抽象為高級 API 和模板。
1、準備工作
添加依賴
- spring data redis
- commons pool
常見配置
- application.yaml
spring:
data:
redis:
# Redis 伺服器的主機地址
host: localhost
# Redis 伺服器的埠
port: 6379
# 配置 Redis 連接池(Lettuce 使用的連接池)
lettuce:
pool:
# 連接池中最大活動連接數
max-active: 8
# 連接池中最大空閑連接數
max-idle: 8
# 連接池中最小空閑連接數
min-idle: 0
# 連接池中最大等待時間
max-wait: 100ms
# Redis 資料庫索引(預設為 0,Redis 預設提供 16 個資料庫)
database: 0
# Redis 伺服器的密碼,用於身份驗證
password: yourpassword
- 配置序列化器
在Spring Data Redis
中,序列化和反序列化是處理 Redis 數據的關鍵部分。序列化是將 Java 對象轉換為位元組流的過程,以便存儲到 Redis 中;反序列化則是將存儲在 Redis 中的位元組流轉換回 Java 對象的過程。Spring Data Redis 提供了多種序列化和反序列化策略,可以根據具體需求進行配置。
配置效果
- 鍵: 被序列化成字元串(例如,
"myKey"
)。 - 值: 被序列化成 JSON 字元串(例如,
{"name":"John","age":30}
)。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
// 創建RedisTemplate對象
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 設置連接工廠
template.setConnectionFactory(connectionFactory);
// 使用 StringRedisSerializer 代替 GenericJackson2JsonRedisSerializer
// GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// 設置key的序列化
template.setKeySerializer(stringRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
template.setValueSerializer(genericJackson2JsonRedisSerializer);
template.setHashValueSerializer(genericJackson2JsonRedisSerializer);
return template;
}
}
2、對數據的操作
Spring Data Redis 提供了一組 API 用於操控 Redis 資料庫。以下是一些常用的 API 及其詳細說明:
1. 字元串操作 (String)
-
設置值
redisTemplate.opsForValue().set("key", "value");
-
獲取值
String value = (String) redisTemplate.opsForValue().get("key");
-
設置值(帶過期時間)
redisTemplate.opsForValue().set("key", "value", Duration.ofMinutes(10));
-
刪除鍵
redisTemplate.delete("key");
2. 哈希操作 (Hash)
-
設置哈希欄位的值
redisTemplate.opsForHash().put("user:1000", "name", "Alice"); redisTemplate.opsForHash().put("user:1000", "email", "[email protected]");
-
獲取哈希欄位的值
String name = (String) redisTemplate.opsForHash().get("user:1000", "name");
-
獲取哈希的所有欄位和值
Map<Object, Object> userMap = redisTemplate.opsForHash().entries("user:1000");
3. 列表操作 (List)
-
右側推入列表
redisTemplate.opsForList().rightPush("list", "value1"); redisTemplate.opsForList().rightPush("list", "value2");
-
左側推入列表
redisTemplate.opsForList().leftPush("list", "value0");
-
獲取列表的所有元素
List<Object> list = redisTemplate.opsForList().range("list", 0, -1);
-
彈出列表的右側元素
Object value = redisTemplate.opsForList().rightPop("list");
4. 集合操作 (Set)
-
添加元素到集合
redisTemplate.opsForSet().add("set", "value1", "value2");
-
獲取集合的所有元素
Set<Object> set = redisTemplate.opsForSet().members("set");
-
移除集合的元素
redisTemplate.opsForSet().remove("set", "value1");
5. 有序集合操作 (Sorted Set)
-
添加元素到有序集合
redisTemplate.opsForZSet().add("zset", "value1", 1); redisTemplate.opsForZSet().add("zset", "value2", 2);
-
獲取有序集合的所有元素
Set<Object> zset = redisTemplate.opsForZSet().range("zset", 0, -1);
-
獲取有序集合的元素及其分數
Set<ZSetOperations.TypedTuple<Object>> zsetWithScores = redisTemplate.opsForZSet().rangeWithScores("zset", 0, -1);
3、RedisTemplate 和 StringRedisTemplate
1. RedisTemplate
RedisTemplate
是一個泛型類,能夠處理不同類型的鍵和值。你可以指定鍵和值的序列化方式,以及 Redis 數據的類型(如 String
, Object
, Hash
, List
, Set
, ZSet
等)。
主要特點:
- 泛型支持: 它支持任意類型的鍵和值,不限於
String
,可以是Object
、Integer
、自定義對象等。 - 序列化方式靈活: 通過設置不同的序列化器,可以對鍵和值進行序列化和反序列化。
2. StringRedisTemplate
StringRedisTemplate
是 RedisTemplate
的一種特化版本,它專門用於操作 String
類型的鍵和值。它預設使用 StringRedisSerializer
來對鍵和值進行序列化和反序列化,因此只處理 String
數據類型。
主要特點:
- 簡化操作: 專註於
String
類型的數據操作,不需要額外配置序列化器,適用於鍵和值都為String
類型的場景。 - 預設序列化方式: 內置
StringRedisSerializer
,預設將鍵和值都序列化為String
。
3. 區別總結
特性 | RedisTemplate |
StringRedisTemplate |
---|---|---|
支持的鍵和值類型 | 支持任何類型(如 String , Object , Integer 等) |
只支持 String 類型的鍵和值 |
序列化方式 | 需要手動配置序列化器(可以選擇 JSON、JDK 序列化等) | 預設使用 StringRedisSerializer ,無需額外配置 |
適用場景 | 適用於複雜的數據類型,如 Object 、JSON 等。 |
適用於簡單的 String 類型數據操作。 |
示例1:
圖一是通過 RedisTemplate
存到 redis 中的 JSON 字元串,圖二是通過 StringRedisTemplate
存到redis 中的 JSON 字元串,由於 RedisTemplate
能夠實現 自動的反序列化,所以需要存儲多餘的 @class
信息,會造成記憶體的浪費。
示例2:
觀察下圖有 @Test
註解的代碼
// Uesr類
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
String name;
Integer age;
}
// 測試
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
void insertUser() {
User user = new User("world", 1);
redisTemplate.opsForValue().set("user:1", user); // 自動將JAVA對象序列換成JSON格式的字元串
User myuser = (User) redisTemplate.opsForValue().get("user:1"); // 自動反序列化,將JSON格式的字元串轉換成JAVA對象
System.out.println("myuser = " + myuser);
}
@Test
void insertUser2() {
User user = new User("world", 2);
String jsonUser = JSON.toJSONString(user); // 手動序列化成JSON格式的字元串
stringRedisTemplate.opsForValue().set("user:1", jsonUser);
String str = stringRedisTemplate.opsForValue().get("user:1");
System.out.println("str = " + str);
User myuser = JSON.parseObject(str, User.class); // 手動從JSON格式的字元串轉換成JAVA對象
System.out.println("myuser = " + myuser);
}
下麵兩張圖分別是第一個Test和第二個Test輸出的結果
通過上面圖可以清楚的看到 RedisTemplate 會自動系列化JSON格式字元串和反序列化成JAVA對象,但是 StringRedisTemplate 都需要手動處理
6、補充
上面用到的JSON處理庫是 fastjson2
, 可在 maven 官網 下載依賴
fastjson 常見用法
// 將 Java 對象序列化為 JSON 字元串
String jsonString = JSON.toJSONString(user);
// 將 JSON 字元串反序列化為 Java 對象
User deserializedUser = JSON.parseObject(jsonString, User.class);
// 創建一個 JSONObject
JSONObject jsonObject = new JSONObject();
jsonObject.put("name", "John");
// 轉換成JSON字元串
jsonObject.toString()
// 解析 JSON 字元串
String jsonString = "{\"name\":\"ld\",\"age\":18,\"city\":\"ShangHai\"}";
JSONObject parsedObject = JSONObject.parseObject(jsonString);
// 獲取value, 輸出 ld
System.out.println("Name: " + parsedObject.getString("name"));
暫且更到這裡 ... 後面再補