mybatis 一对多使用场景
<!-- 一对多查询 -->
<resultMap id="getFilmInfoMap" type="com.stylefeng.guns.api.cinema.vo.FilmInfoVO">
<result column="film_id" property="filmId" />
<result column="film_name" property="filmName" />
<result column="film_length" property="filmLength" />
<result column="film_language" property="filmType" />
<result column="film_cats" property="filmCats" />
<result column="actors" property="actors" />
<result column="img_address" property="imgAddress" />
<collection property="filmFields" ofType="com.stylefeng.guns.api.cinema.vo.FilmFieldVO">
<result column="UUID" property="fieldId"></result>
<result column="begin_time" property="beginTime"></result>
<result column="end_time" property="endTime"></result>
<result column="film_language" property="language"></result>
<result column="hall_name" property="hallName"></result>
<result column="price" property="price"></result>
</collection>
</resultMap>
<select id="getFilmInfos" parameterType="java.lang.Integer" resultMap="getFilmInfoMap">
select
info.film_id,
info.film_name,
info.film_length,
info.film_language,
info.film_cats,
info.actors,
info.img_address,
field.UUID,
field.begin_time,
field.end_time,
field.hall_name,
field.price
from
mooc_hall_film_info_t info
left join
mooc_field_t field
on field.film_id = info.film_id
and field.cinema_id = #{cinemaId}
</select>
Dubbo缓存
结果缓存
1、可以通过注解对热点数据进行缓存
2、Dubbo本地缓存 Redis分布式缓存
3、cache = “lru”
4、结果缓存
Dubbo并发、连接控制
1、对连接和并发数量进行控制
2、超出部分以错误形式返回
3、并发控制
protocol : accepts
provider serviceImpl : executes
consumers: connection
----订----单----模----块----
1、业务开发
2、限流和熔断、降级
3、分组、聚合、版本控制
mac 搭建本地ftp服务器
python -m SimpleHTTPServer
订单模块的横向和纵向拆表 业务复杂度高了
横向:类别拆分
纵向:年份 月份拆分
服务限流
1、系统高可用
2、并发和连接控制进行限流
3、漏桶法 令牌桶
// 因为令牌桶对业务有一定的容忍度
public class TokenBucket {
private int bucketNums=100; // 桶的容量
private int rate=1; // 流入速度
private int nowTokens; // 当前令牌数量
private long timestamp=getNowTime(); // 时间
private long getNowTime(){
return System.currentTimeMillis();
}
private int min(int tokens){
if(bucketNums > tokens){
return tokens;
}else{
return bucketNums;
}
}
public boolean getToken(){
// 记录来拿令牌的时间
long nowTime = getNowTime();
// 添加令牌【判断该有多少个令牌】
nowTokens = nowTokens + (int)((nowTime - timestamp)*rate);
// 添加以后的令牌数量与桶的容量那个小
nowTokens = min(nowTokens);
System.out.println("当前令牌数量"+nowTokens);
// 修改拿令牌的时间
timestamp = nowTime;
// 判断令牌是否足够
if(nowTokens < 1){
return false;
}else{
nowTokens -= 1;
return true;
}
}
}
服务熔断降级
某一个服务器挂掉 — 扇延 导致 雪崩
熔断器 Hystrix
// 依赖
<!-- 熔断器依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
注入
@EnableHystrixDashboard
@EnableCircuitBreaker
@EnableHystrix
实现
public ResponseVO error(Integer fieldId, String soldSeats, String seatsName) {
return ResponseVO.serviceFail("很抱歉,当前购买人数较多,请稍后再试");
}
// 购票
@HystrixCommand(fallbackMethod = "error", commandProperties = {
@HystrixProperty(name="execution.isolation.strategy", value = "THREAD"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value
= "4000"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50")
}, threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "1"),
@HystrixProperty(name = "maxQueueSize", value = "10"),
@HystrixProperty(name = "keepAliveTimeMinutes", value = "1000"),
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "8"),
@HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "12"),
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "1500")
})
@RequestMapping(value = "buyTickets", method = RequestMethod.POST)
public ResponseVO buyTickets(Integer fieldId, String soldSeats, String seatsName) throws IOException {
try {
if (tokenBucket.getToken()) {
// 验证前端参数
// 验证售出的票是否为真
boolean isTrue = orderServiceAPI.isTrueSeats(fieldId + "", soldSeats);
// 已销售的座位里 有没有这些座位
boolean isNotSold = orderServiceAPI.isNotSoldSeats(fieldId + "", soldSeats);
if (isTrue && isNotSold) {
// 创建订单信息
String userId = CurrentUser.getCurrentUserId();
if (userId != null && userId.trim().length()>0) {
OrderVO orderVO = orderServiceAPI.saveOrderInfo(fieldId,soldSeats,seatsName,Integer.parseInt(userId));
if (orderVO == null) {
log.error("购票未成功");
return ResponseVO.serviceFail("购票业务异常");
} else {
return ResponseVO.success(orderVO);
}
} else {
return ResponseVO.serviceFail("用户未登录");
}
} else {
return ResponseVO.serviceFail("订单中的座位编号有问题");
}
} else {
return ResponseVO.serviceFail("购买人数较多,请稍后再试");
}
} catch (Exception e) {
log.error("购票未成功");
return ResponseVO.serviceFail("购票业务异常");
}
}
分组
group:
1、分组进行蓝绿发布版本分布
2、进行同级别压力测试
聚合
提供前端 统一的数据 多表查询聚合结果
多版本的蓝绿上线
版本控制
version
通过蓝绿版本 进行访问控制