前言:

学习的谷粒学院项目,地址:尚硅谷-全栈在线教育项目-谷粒学院【Spring Boot + Spring Cloud Alibaba + Vue.js】_哔哩哔哩_bilibili

根据所学内容总结的知识点。

目录

前言:

1、数据库分库分表

1.1、业务分库

1.2、主从复制和读写分离:

1.3、数据库分表

2、雪花算法:

3、MP(MyBatis-Plus)

3.1、主键策略:

3.2、自动填充

3.3、乐观锁和悲观锁

3.4分页插件

3.5、逻辑删除

4、统一返回结果

5、统一异常处理,特定异常处理,自定义异常

6、阿里云存储OSS服务

7、Nacos

8、OpenFeign

9、服务雪崩

10、服务容错

11、Sentinel

12、关联查询、嵌套查询

13、Redis


1、数据库分库分表

1.1、业务分库

按照业务模块将数据分散到不同的数据库服务器,比如用户数据、商品数据、订单数据存放在三个不同的数据库服务器中,分散存储和访问压力。但也会带来一些问题:

  • join 操作问题:业务分库后,原本在同一个数据库中的表分散到不同数据库中,导致无法使用 SQL 的 join 查询。
  • 事务问题:原本在同一个数据库中不同的表可以在同一个事务中修改,业务分库后,表分散到不同的数据库中,无法通过事务统一修改。
  • 成本问题:业务分库同时也带来了成本的代价,本来 1 台服务器,现在要 3 台,如果考虑备份,那就是 2 台变成了 6 台。

1.2、主从复制和读写分离:

将数据库读写操作分散到不同的节点上。

  • 数据库服务器搭建主从集群,一主一从、一主多从都可以。
  • 数据库主机负责读写操作,从机只负责读操作。
  • 数据库主机通过复制将数据同步到从机,每台数据库服务器都存储了所有的业务数据
  • 业务服务器将写操作发给数据库主机,将读操作发给数据库从机

1.3、数据库分表

单表数据拆分有两种方式:垂直分表和水平分表,用于分散存储压力和提升性能

  • 垂直分表适合将表中某些不常用且占了大量空间的列拆分出去。
  • 水平分表适合表行数特别大的表。

但也会引入复杂性:

水平分表可能存在分布不均匀的问题,一个表中数据非常多,而另一个表中数据非常少。

2、雪花算法:

分布式主键生成算法,它能够保证不同表的主键的不重复性,以及相同表的主键的有序性

  • 长度共64bit(一个long型)。
  • 首先是一个符号位,1bit标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0。
  • 41bit时间截(毫秒级),存储的是时间截的差值(当前时间截 - 开始时间截),结果约等于69.73年。
  • 10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID,可以部署在1024个节点)。
  • 12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID)。

3、MP(MyBatis-Plus)

3.1、主键策略:

MyBatis-Plus默认的主键策略是:ASSIGN_ID (使用了雪花算法)

@TableId(type = IdType.ASSIGN_ID)

AUTO主键自增:

@TableId(type = IdType.AUTO)

3.2、自动填充

如插入时间、更新时间的自动填充。添加@TableField

@Data
public class User {@TableField(fill = FieldFill.INSERT)private Date createTime;//@TableField(fill = FieldFill.UPDATE)@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime;}

同时也要实现元对象处理器接口:


@Component
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {log.info("start insert fill ....");this.setFieldValByName("createTime", new Date(), metaObject);this.setFieldValByName("updateTime", new Date(), metaObject);}@Overridepublic void updateFill(MetaObject metaObject) {log.info("start update fill ....");this.setFieldValByName("updateTime", new Date(), metaObject);}
}

3.3、乐观锁和悲观锁

悲观锁:假设多个线程会同时访问一个共享资源,并且这些线程会试图修改它。悲观锁的策略是假设最坏情况,即认为在任何时候都有可能有另一个线程来修改这个共享资源,因此在访问前会先锁定这个资源,以防止其他线程修改。悲观锁的典型实现是数据库中的行锁或表锁。

乐观锁:相反,乐观锁的策略是认为多个线程同时访问共享资源的概率很小,因此不需要在访问前锁定资源。相反,每次访问共享资源时,先获取一个版本号或时间戳,并在更新数据时检查这个版本号或时间戳是否被其他线程修改过。如果检查到冲突,则放弃当前操作。乐观锁的典型实现是在Java中使用的CAS(Compare And Swap)操作。

在并发控制的选择上,悲观锁一般会降低并发性,因为它会频繁地加锁和解锁资源,而乐观锁则可以更好地保持并发性,因为它只在冲突发生时才进行回滚操作。但是,乐观锁在并发更新高的情况下容易发生冲突,因为每次更新都需要检查版本号或时间戳,这会增加系统的开销。因此,在实际应用中,应该根据具体情况选择适合的并发控制策略。

Mybatis-Plus项目中,使用乐观锁

  • 数据库中添加version字段
  • 添加 @Version 注解
@Version
private Integer version;

创建配置文件并注册乐观锁插件:

@EnableTransactionManagement
@Configuration
@MapperScan("com.atguigu.mybatis_plus.mapper")
public class MybatisPlusConfig {@Beanpublic OptimisticLockerInterceptor optimisticLockerInterceptor() {return new OptimisticLockerInterceptor();
}
}

其中:

@EnableTransactionManagement是Spring Framework中的一个注解,用于启用Spring的事务管理功能。

当多个业务操作可能需要同时对多个数据源进行读写操作。如果这些操作不是原子性的,可能会导致数据不一致或错误的结果。为了解决这个问题,应用程序需要使用事务管理来确保一组业务操作被视为单个操作,即要么全部成功,要么全部回滚。

@EnableTransactionManagement注解会启用Spring框架中的事务管理功能,它会基于AOP机制拦截业务层方法调用,自动管理这些方法中的事务,以确保它们被作为一个单独的操作执行。当使用@EnableTransactionManagement注解时,我们需要在Spring配置文件中配置事务管理器、事务拦截器、数据源等相关内容。

3.4分页插件

添加分页插件配置:

@Bean
public PaginationInterceptor paginationInterceptor() {return new PaginationInterceptor();}

使用分页


@Test
public void testSelectPage() {Page<User> page = new Page<>(1,5);//第一个参数为当前页,第二个为每页的记录个数Page<User> pageParam = userMapper.selectPage(page, null);pageParam.getRecords().forEach(System.out::println); //获取当前页记录System.out.println(pageParam.getCurrent()); //获取当前页System.out.println(pageParam.getPages()); //总页数System.out.println(pageParam.getSize()); //记录个数System.out.println(pageParam.getTotal()); //总记录System.out.println(pageParam.hasNext()); //是否有下一页System.out.println(pageParam.hasPrevious()); //是否有上一页}

返回特定的列:使用结果集Map,例如下学生有姓名、性别、学号、电话、住址等,但是只返回姓名、性别、学号。


@Test
public void testSelectMapsPage() {Page<Map<String, Object>> page = new Page<>(1, 5);QueryWrapper<User> queryWrapper = new QueryWrapper<>();//条件构造器queryWrapper.select("name", "age");//选择要返回的列Page<Map<String, Object>> pageParam = userMapper.selectMapsPage(page, queryWrapper);List<Map<String, Object>> records = pageParam.getRecords();records.forEach(System.out::println);System.out.println(pageParam.getCurrent());System.out.println(pageParam.getPages());System.out.println(pageParam.getSize());System.out.println(pageParam.getTotal());System.out.println(pageParam.hasNext());System.out.println(pageParam.hasPrevious());}

3.5、逻辑删除

  • 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据
  • 逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录
@TableLogic
private Integer deleted;

4、统一返回结果

创建一个返回码定义枚举类,然后创建结果类

5、统一异常处理,特定异常处理,自定义异常

@ControllerAdvice是Spring Framework中的一个注解,用于定义一个全局的异常处理器


@ControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class) //用于处理不同类型的异常@ResponseBodypublic R error(Exception e){e.printStackTrace();return R.error();}
}

添加特定异常处理,比如http异常


@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseBody
public R error(HttpMessageNotReadableException e){e.printStackTrace();return R.setResult(ResultCodeEnum.JSON_PARSE_ERROR);
}

自定义异常:创建自定义异常类,继承RuntimeException

@Data
public class GuliException extends RuntimeException {//状态码private Integer code;/*** 接受状态码和消息* @param code* @param message*/public GuliException(Integer code, String message) {super(message);this.code=code;}/*** 接收枚举类型* @param resultCodeEnum*/public GuliException(ResultCodeEnum resultCodeEnum) {super(resultCodeEnum.getMessage());this.code = resultCodeEnum.getCode();}@Overridepublic String toString() {return "GuliException{" +"code=" + code +", message=" + this.getMessage() +'}';}
}

添加异常处理方法:


@ExceptionHandler(GuliException.class)
@ResponseBody
public R error(GuliException e){log.error(ExceptionUtils.getMessage(e));return R.error().message(e.getMessage()).code(e.getCode());
}

在业务中需要的地方抛出这个异常

public R upload(...) {try {......} catch (Exception e){log.error(ExceptionUtils.getMessage(e));throw new GuliException(ResultCodeEnum.FILE_UPLOAD_ERROR);}
}

6、阿里云存储OSS服务

开通这个服务,会获得相应的keyid,keysecret字段,然后根据官方的技术文档写代码,实现讲师头像的上传和删除。

7、Nacos

  • 引入依赖,
  • 添加配置,将服务注册进Nacos
  • spring:application:name: service-edu # 服务名cloud:nacos:discovery:server-addr: localhost:8848 # nacos服务地址
  • 客户端启动类添加注解@EnableDiscoveryClient

8、OpenFeign

引入依赖,

启动类添加注解@EnableFeignClients

OSS Service中实现业务接口,然后在edu服务中通过OpenFeign远程调用,在创建远程调用接口上加@FeignClient("service-oss"),并在请求方法中添加对应的请求地址

OpenFeign默认使用了负载均衡组件Ribbon,默认策略是轮询策略。

9、服务雪崩

分布式系统环境下,通常会有很多层的服务调用。如果一个服务出现了问题,调用这个服务就会出现线程阻塞的情况,此时若有大量的请求涌入,就会出现多条线程阻塞等待,进而导致服务瘫痪。

由于服务与服务之间的依赖性,故障会传播,不可用沿请求调用链向上传递,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的 “雪崩效应” 。

10、服务容错

隔离、超时、限流、熔断、降级

隔离:将系统划分为若干个服务模块,各个模块之间相对独立,无强依赖。当有故障发生时,能将问题和影响隔离在某个模块内部,而不扩散风险,不波及其它模块,不影响整体的系统服务。常见的隔离方式有:线程池隔离和信号量隔离。

超时:上游服务调用下游服务时,设置一个最大响应时间,如果超过这个时间,下游未作出响应,就断开请求,释放掉线程。

限流:设置流量阈值,一旦达到的需要限制的阈值,就采取相应措施以完成限制流量的目的。比如限制一秒钟一次访问,如果超过了这个频率,就触发限流机制。

熔断:当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用。这种牺牲局部,保全整体的措施就叫做熔断。

降级:降级就是为服务提供一个托底方案,一旦服务无法正常调用,就使用托底方案。

11、Sentinel

Sentinel (分布式系统的流量防卫兵) 是阿里开源的一套用于服务容错的综合性解决方案。它以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度来保护服务的稳定性。我们只需要在项目中引入依赖,添加配置,就可以使用了。

12、关联查询、嵌套查询

13、Redis

首页展示内容用于频繁的读操作,因此可以将其放在Redis缓存中。

引入依赖,添加配置,创建配置类。因为存入Redis中的数据必须序列化,而RedisTemplate默认的序列化方式是JDkSerializationredisSerializer的方式。这种方式对于开发者而言,是及其不友好的,序列化后的内容,不利于开发者查看。所以推荐使用Jackson2JsonRedisSerializer的方式进行。

常用方法:

  • redisTemplate.opsForValue(); //操作字符串
    
  • redisTemplate.opsForHash(); //操作hash
    
  • redisTemplate.opsForList(); //操作list
    
  • redisTemplate.opsForSet(); //操作set
    
  • redisTemplate.opsForZSet(); //操作有序set

使用缓存注解@EnableCaching,将其添加在Redis配置类上方,添加配置


@Bean
public CacheManager cacheManager(LettuceConnectionFactory connectionFactory) {RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()//过期时间600秒.entryTtl(Duration.ofSeconds(600)) // 配置序列化.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())).disableCachingNullValues();RedisCacheManager cacheManager = RedisCacheManager.builder(connectionFactory).cacheDefaults(config).build();return cacheManager;
}

@Cacheable(value = "xxx", key = "'xxx'"):标注在ServiceImpl方法上,对方法返回结果进行缓存。下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不存在,则执行方法,并把返回的结果存入缓存中。一般用在查询方法上。

@Cacheable(value = "index", key = "'selectByAdTypeId'")
@Override
public List<Ad> selectByAdTypeId(String adTypeId) {

谷粒学院项目对应知识点相关推荐

  1. 阿里云短信服务不对个人开放?如何在阿里云市场免费购买短信服务?云市场购买到的短信服务如何使用?(以谷粒学院项目为例)

    问题描述: 在做谷粒学院项目时,需要使用阿里云的短信服务用于注册验证,但是阿里云的短信服务目前不对个人开放了,看到弹幕说可以在云市场购买,于是果断尝试了一把,这过程中又遇到头疼的依赖版本兼容问题,好在 ...

  2. 谷粒学院项目笔记6——oss、EasyExcel、课程分类、nginx

    尚硅谷谷粒学院项目第六天内容之对象存储oss服务.使用EasyExcel添加课程分类功能.课程列表分类.ningx的使用 对象存储oss 打开阿里云官网--对象存储--oss管理控制台 创建bucke ...

  3. 谷粒学院项目讲师管理(二)

    谷粒学院项目讲师管理 一.讲师列表 1.添加讲师列表路由 2.创建路由对应的vue页面 3.第三步在api文件夹创建teacher.js定义访问的接口地址 二.分页查询 三.条件查询 四.讲师添加 五 ...

  4. 【谷粒学院项目开发44】课程大纲——小节的添删

    1.后端 2.前端 2.1"添加小节"按钮 2.2点击"添加小节"按钮,弹出表单 2.3 api 2.4 chapter.vue 2.5 "删除小节& ...

  5. 谷粒学院-数据库设计、搭建项目环境、Mybatis-Plus代码生成器

    数据库设计规约 以下规约只针对本模块,更全面的文档参考<阿里巴巴Java开发手册>:五.MySQL数据库1.库名与应用名称尽量一致2.表名.字段名必须使用小写字母或数字,禁止出现数字开头, ...

  6. 尚硅谷项目 谷粒学院

    尚硅谷项目 谷粒学院 文章目录 尚硅谷项目 谷粒学院 Day01 项目介绍和Mybatis-plus 项目介绍: 1 什么是在线教育 1.1 基本概述 1.2 发展潜力 1.3 适用行业 项目采用技术 ...

  7. 尚硅谷谷粒学院学习笔记(防坑点的总结部分勘误)

    谷粒学院学习笔记 部分勘误 数据库设计规约 模块说明 环境搭建 创建一个Spring Boot 的父工程,版本使用:2.2.1.RELEASE 父工程pom.xml里面添加 在pom.xml中添加依赖 ...

  8. 谷粒学院(五)---Maven从入门到入魔

    前言 我们在日常的javaee项目开发中,对于大量模块的开发管理和jar包的管理,我们难免会设计到maven进行项目的管理,这里我总结Maven中比较重要的一些知识点,这也是我在最近学习的项目谷粒学院 ...

  9. Day206.课程分类【导入功能】前端实现、 课程分类列表【显示功能】、课程管理【模块需求、添加课程功能】 -谷粒学院

    谷粒学院 [课程分类]-导入前端实现 一.配置路由 1.添加路由 src/router/index.js //课程分类{path: 'subject',component: Layout,redire ...

最新文章

  1. 浅析flex中的焦点focus
  2. fiddler 看懂瀑布图Timeline
  3. struts.properties属性解释
  4. 软件测试工程师核心竞争力(转)
  5. JAVA进阶教学之(foreach)
  6. 【DDD】--好文收藏
  7. 给定一个0-1串,请找到一个尽可能长的子串,其中包含的0与1的个数相等。
  8. (23)VHDL实现乘法器
  9. answer的汉语_大概是几乎能满足你们所有要求的两所学校(汉语言文字学、语言学及应用语言学择校攻略)...
  10. python颜色识别,46行代码实现865种颜色识别,看过的都说顶呱呱!
  11. AM335x TP驱动解析
  12. 重置计算机网络设置路由器,重新设置路由器的步骤
  13. 【python基础】英文大小写函数
  14. HTTP 错误 404.0 - Not Found
  15. PPPoE协议交互过程
  16. 家里的网络太慢了,怎么办?
  17. 深度学习论文: Computer Vision for Road Imaging and Pothole Detection: A State-of-the-Art Review
  18. php think-queue队列的安装使用和Supervisor的安装配置和使用
  19. 中国论坛排行榜,热门论坛网站排行榜,热门论坛网站排行榜[转]
  20. 『网络安全』蜜罐到蜜网入门指南(一)蜜罐初识

热门文章

  1. 闪存趋势可能导致用户回归硬盘
  2. 新冠病毒中招|第一天
  3. Domino NSD日志诊断/分析
  4. 智慧外链微信小程序源码1.8版本
  5. 最小公倍数,甲、乙、丙三人是朋友, 他们每隔不同天数到图书馆去一次。 甲3天去一次,乙4天去一次,丙5天去一次。有一天,他们三人恰好在图书馆相会,问至少再过多少天他们三人又在图书馆相会?
  6. 拼多多引流产品卖什么好?拼多多卖什么好?
  7. video标签在安卓下微信x5浏览器的一些问题
  8. k、K、kb、kB、Kb、KB、GB、MB之间的关系
  9. 获取android的实时网速
  10. zigbee知识介绍