京淘專案-12

2020-08-14 19:09:35

1.還原系統設定

1.1 釋放Linux資源

1.1.1 停止數據庫主從服務

在这里插入图片描述

1.1.2 關閉數據庫服務

說明:關閉數據庫伺服器.
在这里插入图片描述

1.1.3 關閉tomcat/mycat伺服器

在这里插入图片描述

1.1.4關閉nginx伺服器

在这里插入图片描述

1.2 修改程式碼中的設定

1.2.1 修改YML組態檔

說明:切換埠號和url地址.
在这里插入图片描述

1.2.2 修改圖片上傳地址

在这里插入图片描述

1.3 修改環境設定

1.3.1 修改hosts檔案

在这里插入图片描述
在这里插入图片描述

1.3.3 存取測試

檢查修改的服務是否有效
在这里插入图片描述

2.Redis快取

2.1 京淘專案架構優化

說明:爲了提高數據庫"查詢"能力.引入快取伺服器.
在这里插入图片描述

2.2 快取機制 機製的介紹

說明:使用快取機制 機製主要的目的就是爲了降低使用者存取物理裝置的頻次.從快取伺服器中直接獲取數據,快速的響應使用者,提高整體的查詢速度.使用者體驗更好.

如何實現:
1.快取機制 機製應該採用什麼樣的數據結構 進行構建? K-V結構 K必須唯一
2.應該使用什麼語言進行開發? C語言
3.快取的執行環境是哪? 記憶體
4.記憶體斷電即擦除, 如何保證數據的安全性?? 實現持久化(寫入磁碟)操作
5.記憶體中的數據如何進行優化 (不能一直存? ) 記憶體優化的演算法 LRU演算法

2.3 Redis介紹

Redis 是一個開源(BSD許可)的,記憶體中的數據結構儲存系統,它可以用作數據庫、快取和訊息中介軟體。 它支援多種型別的數據結構,如 字串(strings), 雜湊(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets)
與範圍查詢, bitmaps, hyperloglogs 和 地理空間(geospatial) 索引半徑查詢。 Redis 內建了 複製(replication),LUA指令碼(Lua scripting), LRU驅動事件(LRU eviction),事務(transactions) 和不同級別的 磁碟持久化(persistence), 並通過 Redis哨兵(Sentinel)和自動 分割區(Cluster)提供高可用性(high availability).
速度快:
tomcat: 150-220/秒
nginx: 3-5萬/秒
redis: 寫 8.6萬/秒 讀 11.2萬/秒 ~ 平均10萬次/秒

Redis安裝

2.3.1 上傳Redis

在这里插入图片描述

2.3.2 解壓Redis

在这里插入图片描述

2.3.3 編譯安裝Redis

1.執行編譯操作 make
在这里插入图片描述
2.安裝redis make install
在这里插入图片描述

2.3.4 修改redis組態檔

:set nu 命令,顯示出行號
1).修改IP系結
在这里插入图片描述
2).取消保護模式
在这里插入图片描述
3).開啓後臺啓動
在这里插入图片描述

2.3.5 Redis常規命令

要求:進入redis根目錄中執行.
特點:redis每次啓動時都會讀取組態檔. 如果需要準備多臺redis則需要準備多個組態檔

1.啓動命令 redis-server redis.conf
沒有開啓後臺執行的效果在这里插入图片描述
開啓後臺執行的效果
在这里插入图片描述
2.檢索redis服務
在这里插入图片描述
3. 進入redis用戶端中
redis-cli (-p 6379) 括號內容根據情況可省略
在这里插入图片描述
4.關閉redis
方式1: redis-cli (-p 6379) shutdown
方式2:
在这里插入图片描述

2.4 Redis入門案例

2.4.1 新增jar包

<!--spring整合redis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
        </dependency>

2.4.2 編輯測試API

package com.jt.test;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;

//@SpringBootTest //需要依賴spring容器,從容器中動態的獲取物件
public class TestRedis {

    /**
     * 完成Redis入門案例測試
     * 報錯說明:
     *      1.檢查Linux防火牆
     *      2.檢查Redis3項設定
     *      3.重新啓動redis.
     */
    @Test
    public void test01(){
        Jedis jedis = new Jedis("192.168.126.129",6379);
        //1.向redis中儲存數據
        jedis.set("2004", "哈哈哈 今天下雨了 不負衆望");
        //2.從redis中獲取數據
        String value = jedis.get("2004");
        System.out.println(value);
    }

    @Test
    public void test02(){
        Jedis jedis = new Jedis("192.168.126.129",6379);

        //1.判斷redis中是否存在key
        if(jedis.exists("2004")){
            //2.如果存在則設定超時時間
            jedis.expire("2004", 100);
            //3.執行緒暫停2秒
            try {
                Thread.sleep(2000);
                //4.獲取剩餘的存活時間
                Long time = jedis.ttl("2004");
                System.out.println("還能活:"+time);
                //5.復原刪除操作
                jedis.persist("2004");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 需求說明:
     *  1.redis.set操作,後面的操作會將之前的value覆蓋
     *  要求:如果key已經存在,則不允許賦值.
     *  注意環境: 檢查redis中是否有改數據.
     *  */
    @Test
    public void test03() {
        //A  潘石屹    B 馬雲
        Jedis jedis = new Jedis("192.168.126.129", 6379);
        jedis.flushAll();   //清空redis快取
        //如果key存在則不執行賦值操作.
        jedis.setnx("boss", "潘石屹");
        jedis.setnx("boss", "馬雲");
        System.out.println(jedis.get("boss"));
    }

    /**
     * 爲數據新增超時時間.保證原子性操作
     * 原子性: 一起完成一起回滾
     * 鎖機制 機製: 保證原子性   死鎖!!!!
     * 小結: setnx 如果key存在則不賦值
     *       setex  保證原子性操作,並且新增超時時間.
     * * */
    @Test
    public void test04() {
        Jedis jedis = new Jedis("192.168.126.129", 6379);
        jedis.setex("aaa", 20, "xxxxx"); //滿足原子性需求.
    }

    /**
     * 需求:
     *  1.要求賦值操作時,如果數據已經存在則不允許賦值.
     *  2.同時要求新增超時時間 並且滿足原子性要求.
     *   private static final String XX = "xx";   只有key存在時,才能 纔能賦值
     *   private static final String NX = "nx";   只有key不存在時,賦值
     *   private static final String PX = "px";   毫秒
     *   private static final String EX = "ex";   秒
     */
    @Test
    public void test05() {
        Jedis jedis = new Jedis("192.168.126.129", 6379);
        SetParams setParams = new SetParams();
        setParams.nx().ex(20);
        jedis.set("AAA", "CCCCC", setParams); //原子性要求
        System.out.println(jedis.get("AAA"));
    }

	 /*測試hash數據型別*/
    @Test
    public void testHash() {
        Jedis jedis = new Jedis("192.168.126.129", 6379);
        jedis.hset("person", "name", "tomcat");
        jedis.hset("person", "age", "100");
        Map<String,String> map = jedis.hgetAll("person");
        System.out.println(map);
    }
	
	@Test
    public void testList() {
        Jedis jedis = new Jedis("192.168.126.129", 6379);
        jedis.lpush("list", "1","2","3","4");
        String value = jedis.rpop("list");
        System.out.println(value);
    }

	 /**
     * 實現Redis 事務控制
     */
    @Test
    public void testMulti() {
        Jedis jedis = new Jedis("192.168.126.129", 6379);
        Transaction transaction = jedis.multi();
        try {
            transaction.set("AAA", "XXX");
            transaction.set("BBB", "XXX");
            transaction.exec(); //提交事務
        }catch (Exception exception){
            exception.printStackTrace();
            transaction.discard();//回滾事務
        }
    }
}

2.5 SpringBoot整合Redis

2.5.1 編輯組態檔

# 設定單台redis
redis.host=192.168.126.129
redis.port=6379

2.5.2 編輯設定類

package com.jt.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import redis.clients.jedis.Jedis;

@Configuration  //標識我是設定類
@PropertySource("classpath:/properties/redis.properties")
public class RedisConfig {

    @Value("${redis.host}")
    private String  host;
    @Value("${redis.port}")
    private Integer port;

    @Bean
    public Jedis jedis(){
        //數據寫死?????????
        return new Jedis(host,port);
    }
}

2.5.3 編輯測試類

說明:校驗springBoot整合是否正確

@SpringBootTest //需要依賴spring容器,從容器中動態的獲取物件
public class TestRedis {

    @Autowired
    private Jedis jedis;
    /**
     * 完成Redis入門案例測試
     * 報錯說明:
     *      1.檢查Linux防火牆
     *      2.檢查Redis3項設定
     *      3.重新啓動redis.
     */
    @Test
    public void test01(){
        //Jedis jedis = new Jedis("192.168.126.129",6379);
        //1.向redis中儲存數據
        jedis.set("2004", "哈哈哈 今天下雨了 不負衆望");
        //2.從redis中獲取數據
        String value = jedis.get("2004");
        System.out.println(value);
    }
}

2.6 數據如何儲存到Redis中

2.6.1 業務說明

說明:由於redis中一般使用String數據型別儲存業務數據.但是程式碼中java物件Redis沒辦法直接儲存,所以需要中間的轉化的過程.使用JSON方式進行數據中轉.
List java物件 --------- JSON ------------ Redis中 使用String數據型別儲存.

2.6.2 ObjectMapper API介紹

package com.jt.test;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jt.pojo.ItemDesc;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class TestObjectMapper {

    private static final ObjectMapper MAPPER = new ObjectMapper();

    @Test
    public void test01(){
        ItemDesc itemDesc = new ItemDesc();
        itemDesc.setItemId(100L).setItemDesc("測試JSON轉化").setCreated(new Date())
                .setUpdated(itemDesc.getCreated());

        try {
            //1.將java物件轉化爲JSON
            String json = MAPPER.writeValueAsString(itemDesc);
            System.out.println(json);
            //2.將JSON轉化爲物件 利用反射機制 機製範例化物件 利用get/set方法爲物件賦值
            ItemDesc itemDesc2 = MAPPER.readValue(json, ItemDesc.class);
            System.out.println(itemDesc2.toString()); //只輸出當前物件的數據

            //3.將集合資訊轉化爲JSON  List
            List<ItemDesc> list = new ArrayList<>();
            list.add(itemDesc);
            String listJSON = MAPPER.writeValueAsString(list);
            System.out.println(listJSON);
            //將json轉化爲List集合
            List<ItemDesc> list2 = MAPPER.readValue(listJSON,list.getClass());
            System.out.println(list2);


        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }
}

2.6.3 編輯工具API

說明:改工具API主要負責將使用者參數轉化爲JSON,或者將JSON串轉化爲物件. 簡化用戶端呼叫
package com.jt.unit;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class ObjectMapperUtil {

//1.建立工具API物件
private static final ObjectMapper MAPPER = new ObjectMapper();

//2.封裝API 將物件轉化爲JSON
public static String toJSON(Object object){

    if(object == null){
        throw new RuntimeException("傳入物件不能爲null");
    }

    try {
        String json = MAPPER.writeValueAsString(object);
        return json;
    } catch (JsonProcessingException e) {
        e.printStackTrace();
        throw new RuntimeException(e.getMessage());
    }
}

/**
 * 3.將JSON串轉化爲物件  使用者傳遞什麼型別,則返回什麼物件
 *                      user.class        User物件
 *
 */
public static <T> T toObject(String json,Class<T> target){

    //1.校驗參數是否有效
    if(json == null || "".equals(json) || target == null){
        //參數有誤.
        throw new RuntimeException("參數不能爲null");
    }

    //2.執行業務處理
    try {
        T t = MAPPER.readValue(json, target);
        return t;
    } catch (JsonProcessingException e) {
        //將報錯資訊通知其他人
        e.printStackTrace();
        throw new RuntimeException(e.getMessage());
    }
}

}

2.6.4 編輯工具API測試

//工具API測試
    @Test
    public void test02(){
        ItemDesc itemDesc = new ItemDesc();
        itemDesc.setItemId(100L).setItemDesc("測試JSON轉化").setCreated(new Date())
                .setUpdated(itemDesc.getCreated());
        String json = ObjectMapperUtil.toJSON(itemDesc);
        ItemDesc itemDesc2 = ObjectMapperUtil.toObject(json, ItemDesc.class);
        System.out.println(itemDesc2);
    }