redis 的相關知識點
啟動
-
啟動程式碼
redis-cli -a 密碼
通用命令
expire: 設定有效期
expire name 10
key
key *
相關資料型別
String
set:新增或者修改已經存在的一個String型別的鍵值對
set age 19
get:根據key獲取String型別的value
get age
mset:批量新增多個String型別的鍵值對
mset k1 v1 k2 v2
mget:根據多個key獲取多個String型別的value
mget k1 k2
incr:讓一個整型的key自增1
incr age
19--->20
incrby:讓一個整型的key自增並指定步長
incrby age 2
incrby age -1
incrbyfloat:讓一個浮點型別的數字自增並指定步長
incrbyfloat score 0.5
setnx:新增一個String型別的鍵值對,前提是這個key不存在,否則不執行
setnx name leixin
setex:新增一個String型別的鍵值對,並且指定有效期
setex names 10 "leixin"
Hash型別
HSET key field value:新增或者修改hash型別key的field的值
hset leixin:name name "leixin"
hset leixin:name name2 "leixin"
HGET key field:獲取一個hash型別key的field的值
hget leixin:name name2
HMSET:批量新增多個hash型別key的field的值
HMGET:批量獲取多個hash型別key的field的值
HGETALL:獲取一個hash型別的key中的所有的field和value
hgetall leixin:name
HKEYS:獲取一個hash型別的key中的所有的field
hkeys leixin:name
HVALS:獲取一個hash型別的key中的所有的value
hvals leixin:name
HINCRBY:讓一個hash型別key的欄位值自增並指定步長
hincrby leixin:name age 2
HSETNX:新增一個hash型別的key的field值,前提是這個field不存在,否則不執行
List
特徵與LinkedList類似:
- 有序
- 元素可以重複
- 插入和刪除快
- 查詢速度一般
- 常用來儲存一個有序資料,例如:朋友圈點贊列表,評論列表等。
如何利用List結構模擬一個棧?
入口和出口在同一邊
如何利用List結構模擬一個佇列?
入口和出口在不同邊
如何利用List結構模擬一個阻塞佇列?
入口和出口在不同邊出隊時採用BLPOP或BRPOP
-
LPUSH key element ... :向列表左側插入一個或多個元素
lpush users 1 2 3 4 5
此時實際為 5 4 3 2 1
-
RPUSH key element ... :向列表右側插入一個或多個元素
rpush users 6 7
此時實際為 5 4 3 2 1 6 7
-
LPOP key count:移除並返回列表左側的count個元素,沒有則返回nil
lpop users 3
此時移除並返回 5 4 3
-
RPOP key count:移除並返回列表右側的count元素
rpop users 3
此時移除並返回的是 7 6 1
-
LRANGE key star end:返回一段角標範圍內的所有元素
lrange users 0 0
此時返回的是 2
-
BLPOP和BRPOP:與LPOP和RPOP類似,只不過在沒有元素時等待指定時間,而不是直接返回nil
blpop users2 100
此時等待中
這個時候新開一個控制檯
lpush users2 1
此時不超過100s的話就會出來結果
1) "users2" 2) "1" (34.91s)
Set
Redis的Set結構與Java中的HashSet類似,可以看做是一個value為null的HashMap。因為也是一個hash表,因此具備與HashSet類似的特徵:
- 無序
- 元素不可重複
- 查詢快
- 支援交集、並集、差集等功能
-
SADD key member ... :向set中新增一個或多個元素
sadd s1 a b c
-
SREM key member ... : 移除set中的指定元素
srem s1 a
-
SCARD key: 返回set中元素的個數
scard s1
-
SISMEMBER key member:判斷一個元素是否存在於set中
sismember s1 b
-
SMEMBERS:獲取set中的所有元素
smembers s1
-
SINTER key1 key2 ... :求key1與key2的交集
-
SDIFF key1 key2 ... :求key1與key2的差集
-
SUNION key1 key2 ..:求key1和key2的並集
SortedSet
- 可排序
- 元素不重複
- 查詢速度快
-
ZADD key score member:新增一個或多個元素到sorted set ,如果已經存在則更新其score值
zadd students 87 jack 88 jerry
-
ZREM key member:刪除sorted set中的一個指定元素
zrem students jack
-
ZSCORE key member : 獲取sorted set中的指定元素的score值
zscore students jerry
-
ZRANK key member:獲取sorted set 中的指定元素的排名
zrank students jerry
排名是從0開始的
-
ZCARD key:獲取sorted set中的元素個數
zcard students
-
ZCOUNT key min max:統計score值在給定範圍內的所有元素的個數
-
ZINCRBY key increment member:讓sorted set中的指定元素自增,步長為指定的increment值
-
ZRANGE key min max:按照score排序後,獲取指定排名範圍內的元素
-
ZRANGEBYSCORE key min max:按照score排序後,獲取指定score範圍內的元素
-
ZDIFF、ZINTER、ZUNION:求差集、交集、並集
-
注意:所有的排名預設都是升序,如果要降序則在命令的Z後面新增REV即可
SpringDataRedis
API | 返回值型別 | 說明 |
---|---|---|
redisTemplate.opsForValue() | ValueOperations | 操作String型別資料 |
redisTemplate.opsForHash() | HashOperations | 操作Hash型別資料 |
redisTemplate.opsForList() | ListOperations | 操作List型別資料 |
redisTemplate.opsForSet() | SetOperations | 操作Set型別資料 |
redisTemplate.opsForZSet() | ZSetOperations | 操作SortedSet型別資料 |
redisTemplate | 通用的命令 |
快速入門
-
匯入依賴
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency>
-
配置檔案
spring: redis: host: 192.168.122.120 port: 6379 password: 73883672 jedis: pool: max-active: 8 max-idle: 0 max-wait: 100ms
-
進行測試
@Autowired private RedisTemplate redisTemplate; @Test void testString() { //寫入一條String資料 redisTemplate.opsForValue().set("name","google"); //獲取String資料 Object name = redisTemplate.opsForValue().get("name"); System.out.println(name); }
-
此時會發現redis資料庫只有一些轉碼了的序列,此時我們需要進行手動序列化
@Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { // 建立RedisTemplate物件 RedisTemplate<String, Object> template = new RedisTemplate<>(); // 設定連線工廠 template.setConnectionFactory(connectionFactory); // 建立JSON序列化工具 GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer(); // 設定Key的序列化 template.setKeySerializer(RedisSerializer.string()); template.setHashKeySerializer(RedisSerializer.string()); // 設定Value的序列化 template.setValueSerializer(jsonRedisSerializer); template.setHashValueSerializer(jsonRedisSerializer); // 返回 return template; } }
-
此時測試注入物件
@Test void testSaveUser(){ //User有兩個引數,一個是name,一個是age redisTemplate.opsForValue().set("user:100",new User("leixin",20)); User o =(User) redisTemplate.opsForValue().get("user:100"); System.out.println("o = "+o); }
-
此時發現多了一個class引數,資料量一大,這是非常浪費空間的。
{ "@class": "com.leixin.pojo.User", "name": "leixin", "age": 20 }
簡單優化
- 使用StringRedisTemplate
- 寫入Redis時,手動把物件序列化為JSON
- 讀取Redis時,手動把讀取到的JSON反序列化為物件
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
void testString(){
stringRedisTemplate.opsForValue().set("name","leixin");
String name = stringRedisTemplate.opsForValue().get("name");
System.out.println(name);
}
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void testSaveUser() throws JsonProcessingException {
// 建立物件
User user = new User("虎哥", 21);
// 手動序列化
String json = mapper.writeValueAsString(user);
// 寫入資料
stringRedisTemplate.opsForValue().set("user:200", json);
// 獲取資料
String jsonUser = stringRedisTemplate.opsForValue().get("user:200");
// 手動反序列化
User user1 = mapper.readValue(jsonUser, User.class);
System.out.println("user1 = " + user1);
}
@Test
void testHash() {
stringRedisTemplate.opsForHash().put("user:400", "name", "虎哥");
stringRedisTemplate.opsForHash().put("user:400", "age", "21");
Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries("user:400");
System.out.println("entries = " + entries);
}