上篇文章:
Redis數據類型之zsethttps://blog.csdn.net/sniper_fandc/article/details/149139955?fromshare=blogdetail&sharetype=blogdetail&sharerId=149139955&sharerefer=PC&sharesource=sniper_fandc&sharefrom=from_link
目錄
1 Redis客戶端和服務器使用自定義協議
2 Java集成Redis
2.1 端口開放
2.2 依賴引入
2.3 測試連接
2.4 set和get測試
2.5 exists和del測試
2.6 keys測試
2.7 expire和ttl測試
2.8 type測試
3 SpringBoot集成Redis
3.1 配置文件
3.2 使用方法
3.2.1 引入依賴
3.2.2 注入Bean
3.2.3 使用redis
1 Redis客戶端和服務器使用自定義協議
????????Redis客戶端和服務器使用自定義協議(應用層)進行網絡通信,即RESP協議。
????????RESP協議是基于序列化的協議,傳輸的數據以字符串格式組織。優點是:1.簡單好實現。2.快速進行解析。3.肉眼可讀。
????????該協議的傳輸層協議是TCP,但是只使用了TCP協議的連接操作,其他的沒再使用。請求和響應之間采用:一問一答的形式。請求發送客戶端的Redis命令的bulk strings數組,響應返回的類型不同,根據不同Redis命令的實現返回不同類型的響應(OK、整數、數組等等)。
????????對于請求和響應的數據的字符串有5種類型:
????????(1)Simple Strings:以+開頭的字符串,只能傳輸簡單的文本,不能傳輸二進制安全的數據。
????????(2)Errors:以-開頭的字符串。
????????(3)Integers:以:開頭的字符串。
????????(4)Bulk Strings:以$開頭的字符串,能傳輸二進制安全的數據。
????????(5)Arrays:以*開頭的字符串。
2 Java集成Redis
2.1 端口開放
????????使用Java訪問Redis如果采用本地方式訪問,即Java程序和Redis服務器在一臺主機上,通過127.0.0.1:6379即可訪問。但是Java客戶端如果想要跨主機訪問Redis客戶端,就必須通過公網IP來訪問,這就會把Redis的端口6379暴露在公網中,很容易遭受黑客入侵。
????????解決辦法是使用ssh協議,配置ssh端口轉發,把遠程Redis服務器的端口號映射到本地主機。ssh協議通常用于Windows與Linux系統網絡交互,默認端口號22,由于ssh協議是加密的網絡傳輸協議,安全程度很高,因此可以構造ssh請求包,把希望訪問Redis端口號6379構造成ssh請求包的數據,通過22端口傳輸到Linux服務器,再由Linux服務器的ssh協議解析請求。
????????由于可能有多個客戶端想要跨主機訪問Linux服務器的其他服務器的端口號,ssh為了區分這些端口號,就會把Linux的各種服務的端口號映射到本地主機(發出訪問請求的主機)的其他端口號(比如Linux的Redis端口6379映射到本地主機8888端口),從而達到客戶端訪問本地端口即可實現訪問Redis端口,這就是ssh的端口轉發功能。客戶端訪問本地端口,其余的事情都有ssh來完成(數據通過ssh協議的加密通道完成傳輸)。
????????這里使用FinalShell終端連接工具,其他終端連接工具都有類似的界面:
????????選擇新建隧道,配置ip和端口號,這里類型是本地,沒有用到跨主機連接(遠程類型)。目標地址是Redis服務器的地址,即Linux的地址。監聽端口表示Redis端口映射到本地的端口是8888:
????????8888端口出現監聽狀態,說明配置成功。
2.2 依賴引入
????????<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.3.2</version></dependency>
2.3 測試連接
????public void testRedis(){JedisPool jedisPool = new JedisPool("tcp://127.0.0.1:8888");try(Jedis jedis = jedisPool.getResource()){String pong = jedis.ping();System.out.println("收到來自Redis服務器的響應:" + pong);}}
????????由于配置了ssh端口轉發,因此這里訪問本機的8888端口即可訪問Redis的服務器。
2.4 set和get測試
????public void testSetAndGet(){try(Jedis jedis = jedisPool.getResource()){SetParams setParams = new SetParams();setParams.px(10);jedis.set("javatest","1");String result = jedis.get("javatest");System.out.println("javatest:" + result);}}
2.5 exists和del測試
????public void existanddel(){try(Jedis jedis = jedisPool.getResource()){jedis.set("javatest","1");Boolean result = jedis.exists("javatest");System.out.println("javatest是否存在?" + result);Long delResult = jedis.del("javatest","javatest2");System.out.println("刪除元素個數:" + delResult);result = jedis.exists("javatest");System.out.println("javatest是否存在?" + result);}}
2.6 keys測試
????public void keys(){try(Jedis jedis = jedisPool.getResource()){jedis.flushAll();jedis.set("javatest","1");jedis.set("javatest2","2");Set<String> result = jedis.keys("*");System.out.println(result.toString());}}
2.7 expire和ttl測試
????public void expireAndTtl(){try(Jedis jedis = jedisPool.getResource()){jedis.flushAll();jedis.set("javatest","1");jedis.expire("javatest",10);System.out.println("等待3s后");Thread.sleep(3000);Long time = jedis.ttl("javatest");System.out.println("剩余的時間:" + time + "s");} catch (InterruptedException e) {throw new RuntimeException(e);}}
2.8 type測試
????public void type(){try(Jedis jedis = jedisPool.getResource()){jedis.flushAll();jedis.set("key1","1");String result1 = jedis.type("key1");System.out.println("key1類型為:" + result1);jedis.lpush("key2","1","2");String result2 = jedis.type("key2");System.out.println("key2類型為:" + result2);jedis.hset("key3","field1","1");String result3 = jedis.type("key3");System.out.println("key3類型為:" + result3);jedis.sadd("key4","1","2");String result4 = jedis.type("key4");System.out.println("key4類型為:" + result4);jedis.zadd("key5",10,"user1");String result5 = jedis.type("key5");System.out.println("key5類型為:" + result5);}}
????????其余的命令不再演示,Jedis提供的Java客戶端訪問Redis的命令基本和Redis客戶端的命令一致,使用很簡單,只是需要注意返回值和變長參數(或者是Map來組織變長參數)。
3 SpringBoot集成Redis
3.1 配置文件
# Redis配置spring:redis:host: 127.0.0.1port: 8888
3.2 使用方法
3.2.1 引入依賴
????????<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
????????該依賴是SpringBoot集成的Redis依賴Spring Data Redis,SpringBoot 2內置的Redis是Lettuce實現,而不是Jedis實現,因此使用上有點區別。
3.2.2 注入Bean
????@Autowiredprivate StringRedisTemplate redisTemplate;
????????這里StringRedisTemplate是已經交付給Spring管理的Bean,它是RedisTemplate的子類。RedisTemplate通過泛型控制是處理文本類型的數據還是處理字節類型的數據。
3.2.3 使用redis
@RequestMapping("/springbootRedis")@RestControllerpublic class RedisController {@Autowiredprivate StringRedisTemplate redisTemplate;@RequestMapping("/test")public void useRedis(){// 使用opsForXXX()方法得到對應類型的操作對象// string類型的操作redisTemplate.opsForValue().set("key","1");String result = redisTemplate.opsForValue().get("key");System.out.println("key:" + result);redisTemplate.delete("key");// list類型的操作redisTemplate.opsForList().leftPush("key", "a");redisTemplate.opsForList().leftPushAll("key", "b", "c", "d");List<String> values = redisTemplate.opsForList().range("key", 1, 2);System.out.println(values);redisTemplate.delete("key");// hash類型的操作redisTemplate.opsForHash().put("key", "name", "zhangsan");String value = (String) redisTemplate.opsForHash().get("key", "name");System.out.println(value);redisTemplate.opsForHash().delete("key", "name");boolean ok = redisTemplate.opsForHash().hasKey("key", "name");System.out.println(ok);redisTemplate.delete("key");// set類型的操作redisTemplate.opsForSet().add("key", "aaa", "bbb", "ccc");boolean ok1 = redisTemplate.opsForSet().isMember("key", "aaa");System.out.println(ok1);redisTemplate.opsForSet().remove("key", "aaa");long n = redisTemplate.opsForSet().size("key");System.out.println(n);redisTemplate.delete("key");// zset類型的操作redisTemplate.opsForZSet().add("key", "user1", 100);redisTemplate.opsForZSet().add("key", "user2", 98);redisTemplate.opsForZSet().add("key", "user3", 95);Set<String> values2 = redisTemplate.opsForZSet().range("key", 0, 2);System.out.println(values2);long n2 = redisTemplate.opsForZSet().count("key", 95, 100);System.out.println(n);redisTemplate.delete("key");}}
????????這里的使用方法是先要用opsForXXX()方法獲取不同類型的操作對象,再通過該操作對象來進行操作。具體的api可能和命令不一樣,但是通過方法的名字也可以知道該方法對應的命令。
下篇文章:
Redis原理之持久化https://blog.csdn.net/sniper_fandc/article/details/149140995?fromshare=blogdetail&sharetype=blogdetail&sharerId=149140995&sharerefer=PC&sharesource=sniper_fandc&sharefrom=from_link