SpringBoot學習筆記9-SpringBoot集成Redis

【Android免費音樂下載app】【佳語音樂下載】建議最少2.0.3版本。最新版本:
https://gitlab.com/gaopinqiang/checkversion/raw/master/Music_Download.apk

Redis Window版本下載地址:https://github.com/microsoftarchive/redis/releases
當前下載的是最新 3.2.100 版本,比linux要落後好多。(沒有折騰VM下裝linux,有時間可以搞個linux虛擬機)
在這裏插入圖片描述

Redis可視化工具:Redis Desktop Manager
下載地址:https://github.com/qishibo/AnotherRedisDesktopManager/releases
如果只是簡單的查看,直接用自帶的redis-cli.exe就可以。也可以使用Redis自帶命令查看

啓動redis服務(2種方式):

  • a.在redis解壓目錄運行cmd,啓動redis命令(cmd關閉,服務停止)
    【redis-server.exe】默認配置啓動
    【redis-server.exe redis.windows-service.conf】配置文件啓動
    在這裏插入圖片描述

  • b.將redis服務安裝到系統,安裝服務後啓動

    【redis-server.exe --service-install redis.windows-service.conf】(會安裝到系統的服務中)
    【redis-server.exe --service-start】(啓動服務)
    【redis-server --service-stop】(停止服務)

設置redis密碼:
將redis.windows-service.conf文件中的配置修改下。
# requirepass foobared
修改成:
requirepass 123456
在通過加載配置文件啓動,通過redis-cli.exe查看是否生效
【auth 123456】輸入密碼連接
在這裏插入圖片描述

Redis服務啓動好,SpringBoot可以集成Redis開發了。

一、SpringBoot 集成 Redis 的步驟如下:(前提啓動了Redis服務)

1、在pom.xml中配置相關的jar依賴;

	<!-- 加載spring boot redis包 -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-data-redis</artifactId>
	</dependency>

2、在Springboot核心配置文件application.properties中配置redis連接信息:

	spring.redis.host=127.0.0.1
	spring.redis.port=6379
	spring.redis.password=123456

3、配置了上面的步驟,Spring boot將自動配置RedisTemplate,在需要操作redis的類中注入redisTemplate;
在使用的類中注入:(ServiceImpl中)
@Autowired
private RedisTemplate<Object, Object> redisTemplate;

StudentServiceImpl.java
	package com.example.mybatis.service.impl;

	import com.example.mybatis.mapper.StudentMapper;
	import com.example.mybatis.model.Student;
	import com.example.mybatis.service.StudentService;
	import org.springframework.beans.factory.annotation.Autowired;
	import org.springframework.data.redis.core.RedisTemplate;
	import org.springframework.stereotype.Service;

	import java.util.List;
	import java.util.Map;

	@Service
	public class StudentServiceImpl implements StudentService {

		@Autowired
		private StudentMapper studentMapper;

		/** 注入springboot自動配置好的RedisTemplate */
		@Autowired
		private RedisTemplate<Object, Object> redisTemplate;

		@Override
		public List<Map<String, Object>> getStudent(String id) {
			return studentMapper.getStudent(id);
		}

		@Override
		public List<Student> getStudent1(String id) {
			List<Student> studentList = (List<Student>) redisTemplate.opsForValue().get("allStudents");

			if(null == studentList){
				studentList = studentMapper.getStudent1(id);
				redisTemplate.opsForValue().set("allStudents",studentList);
				System.out.println("查詢數據庫,將數據存入redis緩存");
			}else{
				System.out.println("查詢Redis緩存");
			}
			return studentList;
		}

		@Override
		public int updateById(Student student) {
			return studentMapper.updateById(student);
		}
	}

SpringBoot幫我們注入的redisTemplate類,泛型裏面只能寫 <String, String>、<Object, Object>
測試運行截圖如下:
在這裏插入圖片描述

這個時候通過Redis的可視化工具,看到已經存入緩存數據。但是鍵值會出現Unicode編碼

	//字符串序列化器
	RedisSerializer redisSerializer = new StringRedisSerializer();
	redisTemplate.setKeySerializer(redisSerializer);

在這裏插入圖片描述

二、Redis高併發條件下的緩存穿透問題。
在一個方法中,有很多人同時請求時候,都會去操作數據庫,並沒有讀取到緩存。比如10000人同時請求,就會請求10000次數據庫。而我們只希望請求一次數據庫。
出現緩存穿透問題截圖如下:
在這裏插入圖片描述

解決的方式就是使用syncronized同步鎖。
可以直接在方法上加鎖。但是這樣會犧牲效率,每次多個請求同時過來,只能一個一個處理。(不推薦)

下面介紹推薦的方式(雙重檢測鎖),代碼如下:

StudentServiceImpl:
    @Override
    public List<Student> getStudent1(String id, String name) {
//        return studentMapper.getStudent1("1","qiang");
//        List<Student> studentList = (List<Student>) redisTemplate.opsForValue().get("allStudents");

        //字符串序列化器
        RedisSerializer redisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(redisSerializer);

        List<Student> studentList = (List<Student>) redisTemplate.opsForValue().get("allStudents");
        //雙重檢測鎖
        if(null == studentList){//第一次請求才會爲空,後面不管多少個人同時請求,都不會走到syncronized代碼處。
            synchronized (this){
                //從redis獲取下
                studentList = (List<Student>) redisTemplate.opsForValue().get("allStudents");

                if(null == studentList){//比如1w人同時請求,第一個人才會使用數據庫,後面的9999人都是使用緩存數據
                    studentList = studentMapper.getStudent1(id,"qiang");
                    redisTemplate.opsForValue().set("allStudents",studentList);
                    System.out.println("查詢數據庫,將數據存入redis緩存");
                }else{
                    System.out.println("查詢Redis緩存");
                }
            }
        }

        return studentList;
    }

測試:

StudentController:
@RequestMapping("/getStudent1")
    public @ResponseBody String getStudent1(){

        //測試Redis緩存
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                studentService.getStudent1("1","qiang");
            }
        };
        //多線程測試下Redis緩存穿透問題
        ExecutorService executorService = Executors.newFixedThreadPool(25);
        for (int i = 0; i < 10000; i++) {
            executorService.submit(runnable);
        }

        List<Student> student = studentService.getStudent1("1","qiang");
        return student.toString();
    }

成功截圖如下:
在這裏插入圖片描述

哨兵模式redis集羣配置:(瞭解下即可,實際開發中再深入研究)
redis:
password: 123456
sentinel:
master: mymaster
nodes: 127.0.0.1:26380,127.0.0.1:26382,127.0.0.1:26384

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章