一SringBoot
一核心:自动配置
二Spring
1IOC控制反转:DI依赖注入
概括
(1):2004年:mF提出:**依赖对象的获得被反转了;**许多应用都是两个或者多个类通过彼此的合作来实现逻辑;这使得每个对象都需要与其合作的对象(也就是它所依赖的对象)的引用;如果这个获取过程要靠自身实现;那么就很耦合,测试复杂;如果交给对象自己去获得依赖对象;
(1) IOC容器:
(1)两个容器系列:
BeanFanctory基类接口: 最基本的功能;
ApplicationContext接口(实现了上面那个); 高级形态
(2) ioc容器初始化:
- **BeanDefinition的定位,*载入,注册三个过程
- 定位:Resource(接口)定位过程;ResourceLoader类;他的isFile(),isxxx()方法等;
- 载入:把用户定义好的Bean表示成ioc容器内部的数据结构,这个结构就是BeanDefinnition,(BeanDefinition(接口)是容器内部的数据结构),
- 注册:ioc容器通过BeanDefinitionRegistry(接口)将BeanDefinition注入到一个HashMap中去,ioc容器通过这个hanshmanp调用;用remove方法删除;
(3)ioc容器的依赖注入:
bean工厂的doGetBean方法().;
(4)BeanFatory和FactoryBean
BeanFatory就是ioc容器或者对象工厂
FactoryBean是一个能容纳产生或者修饰对象生成的工厂bean;
用&转义符可以区分;
2AOP 面向切面编程
(1)概括:
1分离关注点使解决特定领域问题的代码从业务逻辑中独立出来;业务逻辑的代理中不再含有针对特定领域问题代码的调用;
是一种模块化的机制;
2相当于:抽离出来特定领域的代码,封装好,之后统一的调用;
(2)
还封装了业界优秀的AOP解决方案;AspectJ来供应用使用;
(3)AOP术语:
-
目标对象target:类,方法,
-
连接点join point; 对应的是具体被拦截的对象,spring只能支持方法;
-
切点point cut:定义位置,
*service.*.*(..)
-
通知advice:前置,后置,环绕,返回,
-
织入weaving:动态代理,生成代理对象,然后和切点定义的匹配的连接点拦截,并按照约定将各类通知植 入约定流程的过程;
- 运行 时织入:需要为目标生成代理对象;(spring用这种的;所以用到了aop用到了动态代理;两种代理模式,基于接口的使用jdK动态代理,无接口时且不是最终类的时候可以使用CGLB动态代理)
- 编译时织入:需要使用特殊的编译器;
- 装载时织入:需要使用特殊的类装载器;
-
切面aspect:可以定义切点,通知的内容;
(4)动态代理:
基于接口的;Proxy; 和基于类的;
3底层用了动态代理:
- AOP切面织入的时候也可以用到动态代理:
- 动态对象的Bean生成也用了动态代理:proxyFactoryBean类:
三SpringMVC
拦截器
DispatcherServlet:
doDispath()方法核心;
HadlerMappering ;
四Mybatis:
作用:访问数据库;
核心组件:
- Configuration类;–MappedStatement–
- SqlSession是核心;提供了API,例如Excutor;会调用StatemenHandler处理sql;类型转换为TypeHandler,对接JDBC;–ResultSet, 然后获得数据,然后把jdbc数据封装为java层面的,在返回输出;
- MappedStatement:增删改查的入口
- 各种各样的Handler结尾的类;
五Redis:
一:数据结构:
1数据类型:
- string :字符串,数字,二进制数据;键值对都可以是String;String最大可以存储512M的数据;
- list:线性有序,元素可以重复,可以当消息队列使用:两端都可以增删;一个list最多2^32-1个元素;
- hash:最多2^32-1个元素;
- set:无序,不重复,支持多个set求交集,并集,差集;适合求交集(点赞);
- zset:有序,不重复,通过设置一个分数排序;里面有字典:跳表的实现;
2数据类型的编码------>结构------>条件:
- string :int/ras ----->long/SDS(一块内存) -----数据长度超过32字节的字符串;
- list ziplist/linkedlist/quicklist----->压缩列表/双端链表/快速列表
- hash:ziplist/hastable ---->压缩列表/字典
- set: intset/hashteble------整数集合/字典
- zset:; ziplist/skiplist ----->压缩列表/字典+跳表
二3线程模型优点:
(1)单线程:
- io和键值对读写是由一个线程完成的;
- 其他功能:持久化,集群同步数据等都是依赖其他线程 来执行的;
(2)d单线程的优劣:
- 又:单线程避免切换和竞争带来的消耗;简化数据结构和算法的实现;
- 劣:如果某个命令执行时间过长;会造成其他命令的阻塞;
(3):单线程的IO模型:
- 大部分操作是在内存完成的;
- 采用了IO多路复用的机制,可以并发处理大量的客户端请求;(Epol);
- 一个单线程可以同时监视多个套接字Socket;(后端处理的时候,是多线程的);
三4持久性机制;
(1)RDB持久化;
- redis默认的方式,
- 快照的形式把数据持久化到硬盘;
- 通过执行bgsave命令触发
(2)AOF:
- 独立日志的方式;记录每次写入的命令;
- 实时性好;在保证性能的前提下,可以做到最多丢失1秒的数据;(可以设置刷盘效率)
- 比RDB的文件体积大;可以通过重写机制压缩aof文件的体积
(3)RDB-AOF混合
- 4.0开始支持;基于aof实现
- aof重写时,先执行bgsave生成rdb文件,再将文件追加在aof后面;
5ROB持久化实现机制和阻塞:
- 子进程和父进程同时对内存的读取写时;----对于读取内存;是快照;技术;(cope on write);子进程复制了一个快照(照片去读的),然后父进程写的时候就复制一块新的去写;
- 父进程fork子进程的时候,会有一小段时间的阻塞,很小;
6AOF持久化实现机制:
- 追加文件append;
- 重启服务:旧AOF文件 新AOF文件;
- 重写机制:bgrewriteaof
- fork时还是会阻塞;
四:分布式缓存:
1缓存的淘汰策略;
(1)数据过期策略:
- 惰性删除
- 定期删除;贪心算法;随机检测20个,空闲占比超过25%就不在删除;
(2)内存淘汰策略:
- LRU类:最近最少使用的(访问时间更早的);
- LFU类:访问次数最低的,访问时间更早的;
(3) 缓存与数据库的同步:
- 被动:到期淘汰删除缓存;在更新数据库; 下次数据库的数据同步到缓存:
- 主动:先更新数据库;在删除缓存;**建议这种;**才能达到完全同步;通常更合理;异步重试;
商品的维护模块不是我们做的,我们没做更新商品的这个逻辑和后台的管理;我们对模块做了简化,删减,针对于用户的;平台的功能我们没做;但是我们做了库存的逻辑;把库存预热到缓存;先扣减缓存的数据,再把缓存的数据写到数据库,我们做了同步;我们用了RocketmQ的事务型消息;
2分布式常见的问题:
(1)缓存穿透:
- 客户端查询一直根本不存在的数据;使得请求一直直达存储层;甚至使得宕机;
- 解决办法:
- 缓存空对象,存储层未命中时,也在缓存中缓存null.再出访问数据时,缓存层直接返回空值;
- **布隆过滤器:估算:将数据存入布隆过滤器;**为空时自动拦截返回;
(2)缓存击穿:
- 一份热点数据;它的访问量非常大,在其缓存失效的瞬间;大量请求直达存储层;导致服务崩溃;
- 解决方案:
- 热点数据设置永不过期;-----物理的永不过期; (微博的崩溃也是因为热点问题)
- 为每个数据设置逻辑过期时间;当发现逻辑过期时;使用单独的线程重建缓存;
- 加互斥锁:
- 对数据的访问加互斥锁;当一个线程访问该数据时;其他线程等着;这个线程访问过后;缓存中的数据将被重建;届时其他线程就可以从缓存中取值;
(3)缓存雪崩:
- 整个缓存层挂了;导致所有的 请求直达存储层;可能是缓存中有大量数据同时过期;也可能是Redis节点发生故障;导致大量请求无法被处理;
- 解决方案:
- 避免数据同时过期,附加一个随机数;避免大量的key同时过期;
- 启用降级和熔断措施:
- 发生雪崩时;若访问的不是核心数据;直接返回预定义的信息/空值等;并且,对于访问缓存接口的请求;客户端直接不会吧请求发给Redies ;减少压力;而是直接返回;
- 构建高可用的缓存服务:
- 采用哨兵模式或者集群模式;部署多个Redis,个别宕机,还能保持服务的整体可用;
六RocketMQ:
RicketMQ 继承了kafaka;增强了交易型,适合更多的业务场景,她的官方手册是中文的;