高並發下Redis會出現的問題:
- 緩存穿透
- 緩存雪崩
- 熱點緩存
一、定義commons工程11-dubboCommons
(1) 創建工程
創建Maven的Java工程,並命名為11-dubboCommons
(2) 定義pom文件
-
<groupId>com.abc
</groupId>
-
<artifactId>11-dubboCommons
</artifactId>
-
<version>1.0-SNAPSHOT
</version>
-
-
<properties>
-
<project.build.sourceEncoding>UTF-8
</project.build.sourceEncoding>
-
<maven.compiler.source>1.8
</maven.compiler.source>
-
<maven.compiler.target>1.8
</maven.compiler.target>
-
</properties>
-
-
<dependencies>
-
<dependency>
-
<groupId>org.projectlombok
</groupId>
-
<artifactId>lombok
</artifactId>
-
<version>1.18.4
</version>
-
<scope>provided
</scope>
-
</dependency>
-
</dependencies>
(3) 定義實體類
(4) 定義業務接口
(5) 將工程安裝到本地庫
運行Maven的install命令,將工程安裝到本地版本庫,以備其它工程使用
二、定義提供者11-provider-springboot
(1) 創建工程
創建一個Spring Boot工程,並重命名為11-provider-springboot
(2) 定義pom文件
A、添加dubbo與spring boot整合依賴
B、添加zkClient依賴
C、其它依賴
- dubboCommons依賴
- spring boot與redis整合依賴
- mybatis與spring boot整合依賴
- 數據源Druid依賴
- mysql驅動依賴
- slf4j-log4j12依賴
- spring-boot-starter-web依賴
-
<groupId>com.abc
</groupId>
-
<artifactId>11-provider-springboot
</artifactId>
-
<version>0.0.1-SNAPSHOT
</version>
-
-
<parent>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-parent
</artifactId>
-
<version>2.1.5.RELEASE
</version>
-
<relativePath/>
<!-- lookup parent from repository -->
-
</parent>
-
-
<properties>
-
<project.build.sourceEncoding>UTF-8
</project.build.sourceEncoding>
-
<project.reporting.outputEncoding>UTF-8
</project.reporting.outputEncoding>
-
<java.version>1.8
</java.version>
-
</properties>
-
-
<dependencies>
-
<!--dubbo與spring boot整合依賴-->
-
<dependency>
-
<groupId>com.alibaba.spring.boot
</groupId>
-
<artifactId>dubbo-spring-boot-starter
</artifactId>
-
<version>2.0.0
</version>
-
</dependency>
-
<!-- zk客戶端依賴:zkclient -->
-
<dependency>
-
<groupId>com.101tec
</groupId>
-
<artifactId>zkclient
</artifactId>
-
<version>0.10
</version>
-
</dependency>
-
<dependency>
-
<groupId>com.abc
</groupId>
-
<artifactId>11-dubboCommons
</artifactId>
-
<version>1.0-SNAPSHOT
</version>
-
</dependency>
-
<!--Spring Boot與Redis整合依賴-->
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-data-redis
</artifactId>
-
</dependency>
-
<!--mybatis與Spring Boot整合依賴-->
-
<dependency>
-
<groupId>org.mybatis.spring.boot
</groupId>
-
<artifactId>mybatis-spring-boot-starter
</artifactId>
-
<version>1.3.2
</version>
-
</dependency>
-
<!--數據源Druid依賴-->
-
<dependency>
-
<groupId>com.alibaba
</groupId>
-
<artifactId>druid
</artifactId>
-
<version>1.1.10
</version>
-
</dependency>
-
<!--MySQL驅動依賴-->
-
<dependency>
-
<groupId>mysql
</groupId>
-
<artifactId>mysql-connector-java
</artifactId>
-
<version>5.1.47
</version>
-
</dependency>
-
<dependency>
-
<groupId>org.slf4j
</groupId>
-
<artifactId>slf4j-log4j12
</artifactId>
-
<version>1.7.25
</version>
-
<scope>test
</scope>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-web
</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-test
</artifactId>
-
<scope>test
</scope>
-
</dependency>
-
</dependencies>
-
-
<build>
-
<plugins>
-
<plugin>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-maven-plugin
</artifactId>
-
</plugin>
-
</plugins>
-
-
<resources>
-
<!--注冊dao包下mybatis映射文件為資源目錄-->
-
<resource>
-
<directory>src/main/java
</directory>
-
<includes>
-
<include>**/*.xml
</include>
-
</includes>
-
</resource>
-
</resources>
-
</build>
(3) 定義Service實現類
-
import com.abc.bean.Employee;
-
import com.abc.dao.EmployeeDao;
-
import com.alibaba.dubbo.config.
annotation.Service;
-
import org.springframework.beans.factory.
annotation.Autowired;
-
import org.springframework.cache.
annotation.CacheEvict;
-
import org.springframework.cache.
annotation.Cacheable;
-
import org.springframework.
data.redis.core.BoundValueOperations;
-
import org.springframework.
data.redis.core.RedisTemplate;
-
import org.springframework.stereotype.Component;
-
import org.springframework.transaction.
annotation.Transactional;
-
-
import java.util.concurrent.TimeUnit;
-
-
@Service
// Dubbo的注解 <dubbo:service/>
-
@Component
-
public
class EmployeeServiceImpl implements EmployeeService {
-
@Autowired
-
private EmployeeDao dao;
-
@Autowired
-
private RedisTemplate<Object, Object> redisTemplate;
-
-
// 當有對象插入時會清空realTimeCache緩存空間
-
@CacheEvict(value="realTimeCache", allEntries = true)
-
@Transactional(rollbackFor = Exception.class)
-
@Override
-
public void addEmployee(Employee employee) {
-
dao.insertEmployee(employee);
-
}
-
-
// 一旦有了查詢結果,則會將此結果寫入到realTimeCache緩存
-
// key是employee_加上方法參數
-
@Cacheable(value = {"realTimeCache"}, key = "'employee_'+#id")
-
@Override
-
public Employee findEmployeeById(int id) {
-
// 從DB查詢
-
System.
out.println(
"從DB查詢id = " + id);
-
return dao.selectEmployeeById(id);
-
}
-
-
private
volatile Object count;
-
// 雙重檢測鎖機制解決Reids的熱點緩存問題
-
@Override
-
public Integer findEmployeeCount() {
-
// 獲取Redis操作對象
-
BoundValueOperations<Object, Object> ops = redisTemplate.boundValueOps(
"count");
-
// 從緩存獲取數據
-
count = ops.
get();
-
if(count ==
null) {
-
synchronized (
this) {
-
count = ops.
get();
-
if(count ==
null) {
-
System.
out.println(
"從DB中查詢");
-
// 從DB中查詢
-
count = dao.selectEmployeeCount();
-
// 將查詢結果存放到Redis
-
ops.
set(count,
10, TimeUnit.SECONDS);
-
}
-
}
-
}
-
return (Integer) count;
-
}
-
}
(4) 定義Dao接口
(5) 定義映射文件
(6) 修改啟動類
在啟動類上必須要添加@EnableDubboConfiguration注解,開啟Dubbo的自動配置功能
(7) 修改主配置文件
-
server:
-
port: 8888
-
-
mybatis:
-
# 注冊mybatis中實體類的別名
-
type-aliases-package: com.abc.bean
-
# 注冊映射文件
-
mapper-locations: classpath:com/abc/dao/*.xml
-
-
spring:
-
# 注冊數據源
-
datasource:
-
# 指定數據源類型為Druid
-
type: com.alibaba.druid.pool.DruidDataSource
-
driver-class-name: com.mysql.jdbc.Driver
-
url: jdbc:mysql:///
test?useUnicode=
true&characterEncoding=utf8
-
username: root
-
password: root
-
-
# 連接Redis服務器
-
redis:
-
host: 39.97.176.160
-
port: 6379
-
-
# 連接Redis高可有集群
-
# redis:
-
# sentinel:
-
# master: mymaster
-
# nodes:
-
# - sentinelOS1:26379
-
# - sentinelOS2:26379
-
# - sentinelOS3:26379
-
-
# 配置緩存
-
cache:
-
type: redis
# 指定緩存類型
-
cache-names: realTimeCache
# 指定緩存區域名稱
-
-
-
# 功能等價於spring-boot配置文件中的<dubbo:application/>
-
application:
-
name: 11-provider-springboot
-
# 指定zk注冊中心
-
dubbo:
-
registry: zookeeper://39.97.176.160:2181
-
# zk集群作注冊中心
-
# registry: zookeeper://zkOS1:2181?backup=zkOS2:2181,zkOS3:2181
三、定義消費者11-consumer-springboot
(1) 創建工程
創建一個Spring Boot工程,並重命名為11-consumer-springboot
(2) 定義pom文件
- dubbo與spring boot整合依賴
- zkClient依賴
- dubboCommons依賴
- JSP引擎jasper依賴
- slf4j-log4j12依賴
- spring-boot-starter-web依賴
(3) 修改主配置文件
-
spring:
-
# 功能等價於spring-dubbo配置文件中的<dubbo:application/>
-
application:
-
name:
11-consumer-springboot
-
# 指定zk注冊中心
-
dubbo:
-
registry: zookeeper:
//39.97.176.160:2181
-
# zk集群作注冊中心
-
# registry: zookeeper://zkOS1:2181?backup=zkOS2:2181,zkOS3:2181
(4) 創建index.jsp頁面
在src/main/webapp目錄下定義index.jsp文件
(5) 定義處理器
-
package com.abc.controller;
-
-
import com.abc.bean.Employee;
-
import com.abc.service.EmployeeService;
-
import com.alibaba.dubbo.config.
annotation.Reference;
-
import org.springframework.stereotype.Controller;
-
import org.springframework.ui.Model;
-
import org.springframework.web.bind.
annotation.PathVariable;
-
import org.springframework.web.bind.
annotation.PostMapping;
-
import org.springframework.web.bind.
annotation.RequestMapping;
-
import org.springframework.web.bind.
annotation.ResponseBody;
-
-
@Controller
-
@RequestMapping("/consumer/employee")
-
public
class SomeController {
-
-
// @Autowired
-
@Reference
// Dubbo的注解 <dubbo:reference />
-
private EmployeeService employeeService;
-
-
@PostMapping("/register")
-
public String someHandle(Employee employee, Model model) {
-
employeeService.addEmployee(employee);
-
model.addAttribute(
"employee", employee);
-
return
"/welcome.jsp";
-
}
-
-
@RequestMapping("/find/{id}")
-
@ResponseBody
-
public Employee findHandle(
@PathVariable("id") int id) {
-
return employeeService.findEmployeeById(id);
-
}
-
-
@RequestMapping("/count")
-
@ResponseBody
-
public Integer countHandle() {
-
return employeeService.findEmployeeCount();
-
}
-
-
}
(6) 定義welcome.jsp頁面
(7) 修改入口類
四、測試
當有對象插入時會清空realTimeCache緩存空間
一旦有了查詢結果,則會將此結果寫入到realTimeCache緩存
http://localhost:8080/index.jsp 首頁
http://localhost:8080//consumer/employee/find/2 根據Id查找
http://localhost:8080//consumer/employee/count 查找總數