億級併發|day09-Redis進階
1 Redis命令
1.Hash型別 說明:可以用雜湊型別儲存物件和屬性的值,表現為value部分為一個HashMap。 例子:User物件{id:2, name:小明, age:19}
2.List型別 說明:Redis中的List集合是雙端迴圈列表(雙向列表),分別可以從左右兩個方向插入資料。 List集合可以當做佇列來使用,也可以當做棧來使用。 佇列:先進先出,存/取資料的方向不一致。 棧:先進後出,存/取資料的方向一致。
3.Redis事務命令 業務需求:
- redis可以當做資料庫使用。
- 有時插入快取時,可能多資料一起插入,所以需要事務控制。
說明:redis中操作可以新增事務的支援,一項任務可以由多個redis命令完成,如果有一個命令失敗導致入庫失敗時,需要實現事務回滾。
2 Redis入門案例
2.1 引入jar包
<!-- jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
<!--新增spring-datajar包 -->
<dependency>
<groupId>org.springframework.data</ groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.4.1.RELEASE</version>
</dependency>
2.2 測試字串
//測試String型別 IP:埠
/**
* 1.檢測防火牆是否關閉了
* 2.檢查IP繫結是否註釋了 預設繫結本機(Linux) #bind ip 關閉後重啟
* 3.保護模式是否關閉 預設值yes 改為no 修改後重啟
* 4.啟動方式不對...... redis-server redis.conf
*/
@Test
public void testString(){
Jedis jedis = new Jedis("192.168.126.166", 6379);
Long start = System.currentTimeMillis();
jedis.set("1806","今天星期一困的不行,一週總有那麼7天不想上課");
Long end = System.currentTimeMillis();
System.out.println(end-start+"毫秒");
System.out.println
("獲取redis內容:"+jedis.get("1806"));
}
2.3 測試Hash
//測試hash值 讀11萬/s 寫8.1萬/s 10萬/s
@Test
public void testHash(){
Jedis jedis = new Jedis("192.168.126.166", 6379);
jedis.hset("person", "id", "100");
jedis.hset("person", "name", "1806班");
jedis.hset("person", "age", "4");
Map<String,String> map = jedis.hgetAll("person");
System.out.println(map);
}
2.4 測試List
@Test
public void testList(){
Jedis jedis = new Jedis("192.168.126.166", 6379);
//下面程式碼中是可變引數 使用,號分割
jedis.lpush("list","1","2","3","4");
System.out.println(jedis.rpop("list"));
}
2.5 Redis事務控制
/**
* redis.clients.jedis.exceptions.JedisDataException: Cannot use Jedis when in Multi. Please use JedisTransaction instead.
* 說明:因為使用redis事務控制需要開啟事務/提交事務/回滾事務
* 這部分程式碼如果直接寫入業務層,則程式碼的耦合性高
* 所以可以通過AOP+自定義註解redisTx
* 抽空說說
*/
@Test
public void testTx(){
Jedis jedis = new Jedis("192.168.126.166", 6379);
//開啟事務控制
Transaction tansaction = jedis.multi();
//執行入庫操作
tansaction.set("aa", "事務測試");
tansaction.set("bb", "bb");
//事務提交
//tansaction.exec();
//事務回滾
tansaction.discard();
System.out.println("獲取資料:"+jedis.get("aa"));
}
3 Spring整合Redis
3.1 編輯pro檔案
1.新建redis.properties檔案
redis.host=192.168.126.166
redis.port=6379
2.匯入配置檔案
<list>
<value>classpath:/property/jdbc.properties</value>
<value>classpath:/property/redis.properties</value>
</list>
3.2 編輯配置檔案
<!--spring整合redis
Jedis jedis = new Jedis("192.168.126.166", 6379);
關於構造注入的注意事項
1.name屬性:代表構造方法中的引數名稱
注意事項:在使用構造注入時,程式打包部署時最好新增原始碼!!!!
如果沒有匯入原始碼.那麼程式不會維護形參 則名稱為arg0,arg1,arg2.
2.index屬性
表示下標,從0開始.根據引數位置匹配構造方法.
User(String a,String b)
User(int a,String b)
User(Dog dog,String a)
3.type=""屬性
表示引數型別,一般預設不寫.由spring框架內部自動進行強轉.
所以在為引數賦值時,必須嚴格的規範構造方法.否則
注入會有問題.
-->
<!-- <bean id="jedis" class="redis.clients.jedis.Jedis">
<constructor-arg index="0" value="${redis.host}" type="Dog"/>
<constructor-arg index="1" value="${redis.port}" type="int"/>
</bean> -->
<bean id="jedis" class="redis.clients.jedis.Jedis">
<constructor-arg name="host" value="${redis.host}"/>
<constructor-arg name="port" value="${redis.port}"/>
</bean>
4 JSON回顧
4.1 json官網介紹
JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。 易於人閱讀和編寫。
4.2 object格式
語法:
- 物件是一個無序的名稱/值對集合
- 一個物件以"{"(左大括號)開始,"}"(右大括號)結束
- 每個名稱後跟一個":"(冒號)
- 名稱/值對之間使用","(逗號)分割
{key:value}
例子:{“id”:“1”,“name”:“tom”} 簡單寫法:key和數字可以不加引號
4.3 array格式
說明:通過陣列形式儲存資料 格式:陣列·是·值(value)的有序集合,一個數組以"["(左中括號)開始,"]"(右中括號)結束,值之間用","(逗號)分隔。 [value1,value2,value3] 圖例:
例子:[1,2,3,4,5,“tom”]
4.4 複雜格式
特點:可以將object格式和array格式進行·無限層級巢狀 說明:值(value)可以是雙括號括起來的字串(string)、數值(number)、true、false、null、物件(object)或者陣列(array)。這些結構可以巢狀。
圖例:
例子:
{
id:1,
name:"tomcat",
hobby:[
["早點","午飯","下午茶"],
"喝",
{
where:"沙灘",
time:"半夜",
with:"鯊魚"
}
]
}
5 JSON與物件轉化
5.1 物件轉為JSON串
//將物件轉化為JSON
@Test
public void ObjectToJSON() throws JsonProcessingException{
User user = new User();
user.setId(1);
user.setName("tomcat貓");
user.setAge(19);
ObjectMapper objectMapper = new ObjectMapper();
//轉化時呼叫物件的getXXX()
String json =
objectMapper.writeValueAsString(user);
System.out.println(json);
}
5.2 JSON轉物件
@Test
public void jsonToObject() throws JsonParseException, JsonMappingException, IOException{
String json = "{\"id\":\"1\",\"name\":\"tomcat\"}";
ObjectMapper objectMapper = new ObjectMapper();
User user = objectMapper.readValue(json,User.class);
System.out.println(user);
}
5.3 複雜格式轉化
@Test
public void jsonOA() throws IOException{
List<User> userList = new ArrayList<>();
User user1 = new User();
user1.setId(1);
user1.setName("tomcat貓");
user1.setAge(19);
user1.setSex("男");
User user2 = new User();
user2.setId(2);
user2.setName("tomcat貓");
user2.setAge(19);
user2.setSex("男");
userList.add(user1);
userList.add(user2);
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(userList);
//System.out.println("獲取JSON串:"+json);
//2.將複雜格式的JSON轉化為物件List
//List<User> uList =
//objectMapper.readValue(json, userList.getClass());
//System.out.println("獲取物件:"+uList);
User[] users =
objectMapper.readValue(json,User[].class);
//將陣列轉化為List集合
List<User> uList = Arrays.asList(users);
System.out.println(uList);
}
6 快取實現商品分類查詢
6.1 快取實現步驟
1.修改業務邏輯,首先使用者查詢先查詢redis快取 2.如果無快取資料,表示第一次查詢該資料,則先從資料庫查詢 3.找到資料後,將資料通過API轉化為JSON串,將資料k-v寫入快取中 4.如果快取資料不為null,則將JSON串轉化為java物件,直接return返回。
6.2 編輯controller
/**
* 實現商品分類目錄展現
* @RequestParam
* defaultValue= 如果沒有傳遞引數 預設值為...
* required=true/false 預設為false 如果true 那麼前臺必須傳遞該引數.
* value 需要轉化變數的名稱
* @param parentId
* @return
*/
@RequestMapping("/list")
@ResponseBody
public List<EasyUITree> findItemCatById(
@RequestParam(value="id",
defaultValue="0")
Long parentId){
//查詢一級商品分類目錄
//Long parentId = 0L;
//return itemCatService.findItemCatById(parentId);
return itemCatService.findCacheItemCatById(parentId);
}
6.3 編輯service
1.注入物件
2.業務程式碼
//通過redis快取實現資訊查詢
@Override
public List<EasyUITree> findCacheItemCatById(Long parentId) {
List<EasyUITree> treeList = null;
//1.先查詢快取資料
String key = "ITEM_CAT_"+parentId;
String resultJSON = jedis.get(key);
try {
//2.判斷快取中是否有資料
if(StringUtils.isEmpty(resultJSON)){
//2.1表示快取中沒有資料,需要查詢後臺資料庫
treeList = findItemCatById(parentId);
//2.2將java物件轉化為JSON串
String jsonData = objectMapper.writeValueAsString(treeList);
//2.3將資料寫入快取
jedis.set(key, jsonData);
System.out.println("第一次查詢資料庫");
}else {
//3.快取中有資料
//3.1將JSON串轉化為java物件(List)
EasyUITree[] trees =
objectMapper.readValue(resultJSON,EasyUITree[].class);
treeList = Arrays.asList(trees);
System.out.println("查詢快取資料");
}
} catch (Exception e) {
e.printStackTrace();
}
return treeList;
}
6.4 時間比較
1.沒有新增快取時
2.新增快取時