3.mem dump中unreachable objects分析
4.tcp滑动窗口作用
- 保证tcp的可靠性
- 保证tcp的流控特性
AdvertisedWindow
接收方能接受的大小,EffectiveWindow
发送方还能发送数据的大小
5.请求/响应的步骤
- 客户端连接到web服务器
- 发送Http请求
- 服务器接受请求并返回http响应
- 释放tcp连接(closed:服务器主动关闭,keep-alive:连接会保留一段时间)
- 客户端浏览器解析html内容
6.tcp/ip协议的四层模型
应用层,传输层,网络互联层,主机到网络层
image.png image.png
7.如何设计一个数据库
image.png
8.innodb和myisam区别
myisam 默认表级锁,不支持行级锁
读锁为:共享锁,查询为读锁
写锁为:排他锁,增删改为写锁
相关命令:
手动加读锁:lock tables 表名 read
手动释放锁:unlock tables
对select上排他锁:select * from person_info_myisam for update
innodb 默认行级锁,支持表级锁,支持事务
- 在查询数据时,若sql不含索引,使用表级锁,否则,使用行级锁,或者get锁(普通非唯一索引)
- 表级的意向锁,分为:IS(共享读锁),IX(排他写锁)
读锁为:共享锁,查询为读锁
写锁为:排他锁,增删改为写锁
相关命令:
查看事务是否自动提交:show variables like 'autocommit'
关闭自动提交:set autocommit = 0
对select上读锁:select * from person_info_myisam lock in share mode
9.事务隔离级别
命令:
查看当前事务级别:select @@tx_isolation
设置当前session的事务隔离级别(未提交读 脏读):set session transaction isolation level read uncommitted
10.对主键索引或者唯一索引会用Gap锁吗
1.如果where条件全部命中,则不会用Gap锁,只会加记录锁
2.如果where条件部分命中或者全不命中,则会加Gap锁
3.Gap锁会用在非唯一索引或者不走索引的当前读中
11.classloader的种类
- BootStrapClassLoader :c++编写,加载核心库java.*
- ExtClassLoader:java编写,加载扩展库javax.*
- AppClassLoader:java编写,加载程序所在目录
- 自定义ClassLoader:Java编写,定制化加载
12.解决哈希(HASH)冲突的主要方法
数据结构与算法:hash冲突解决
13.elasticsearch原理
反向索引又叫倒排索引,是根据文章内容中的关键字建立索引
建立倒排索引,基于 Lucene 库进行封装,将对搜索引擎的操作都封装成restful的api,同时还考虑了海量数据,实现了分布式,是一个可以存储海量数据的分布式搜索引擎。
14.spring 自动装配发展
- 模式注解,@component,@since 2.5
- @Enable模块实现,@EnableServer 参考 @EnableCaching实现,@since 3.1
//1.定义接口
public interface Server {
/**
* 启动服务器
*/
void start();
/**
* 关闭服务器
*/
void stop();
/**
* 服务器类型
*/
enum Type {
HTTP, // HTTP 服务器
FTP // FTP 服务器
}
}
2.实现上述定义的server接口
@Component // 根据 ImportSelector 的契约,请确保是实现为 Spring 组件
public class FtpServer implements Server {
@Override
public void start() {
System.out.println("FTP 服务器启动中...");
}
@Override
public void stop() {
System.out.println("FTP 服务器关闭中...");
}
}
3.实现上述定义的server接口
@Component // 根据 ImportSelector 的契约,请确保是实现为 Spring 组件
public class HttpServer implements Server {
@Override
public void start() {
System.out.println("HTTP 服务器启动中...");
}
@Override
public void stop() {
System.out.println("HTTP 服务器关闭中...");
}
}
4.自定义Enable注解,666
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//@Import(ServerImportSelector.class) // 导入 ServerImportSelector
@Import(ServerImportBeanDefinitionRegistrar.class) // 替换 ServerImportSelector
public @interface EnableServer {
/**
* 设置服务器类型
* @return non-null
*/
Server.Type type();
}
5.类似enablecache的importselector接口实现
public class ServerImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 读取 EnableServer 中的所有的属性方法,本例中仅有 type() 属性方法
// 其中 key 为 属性方法的名称,value 为属性方法返回对象
Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(EnableServer.class.getName());
// 获取名为"type" 的属相方法,并且强制转化成 Server.Type 类型
Server.Type type = (Server.Type) annotationAttributes.get("type");
// 导入的类名称数组
String[] importClassNames = new String[0];
switch (type) {
case HTTP: // 当设置 HTTP 服务器类型时,返回 HttpServer 组件
importClassNames = new String[]{HttpServer.class.getName()};
break;
case FTP: // 当设置 FTP 服务器类型时,返回 FtpServer 组件
importClassNames = new String[]{FtpServer.class.getName()};
break;
}
return importClassNames;
}
}
6.注册到 BeanDefinitionRegistry,这里解释一下,如果server接口的实现类(httpserver,ftpserver)没有被定义成bean(例如:没有Component 注解),就需要进行bean的注册
public class ServerImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 复用 {@link ServerImportSelector} 实现,避免重复劳动
ImportSelector importSelector = new ServerImportSelector();
// 筛选 Class 名称集合
String[] selectedClassNames = importSelector.selectImports(importingClassMetadata);
// 创建 Bean 定义
Stream.of(selectedClassNames)
.map(BeanDefinitionBuilder::genericBeanDefinition) // 转化为 BeanDefinitionBuilder 对象
.map(BeanDefinitionBuilder::getBeanDefinition) // 转化为 BeanDefinition
.forEach(beanDefinition ->
// 注册 BeanDefinition 到 BeanDefinitionRegistry
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry)
);
}
}
7.引导类进行测试
@Configuration
@EnableServer(type = Server.Type.HTTP) // 设置 HTTP 服务器
public class EnableServerBootstrap {
public static void main(String[] args) {
// 构建 Annotation 配置驱动 Spring 上下文
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 注册 当前引导类(被 @Configuration 标注) 到 Spring 上下文
context.register(EnableServerBootstrap.class);
// 启动上下文
context.refresh();
// 获取 Server Bean 对象,实际为 HttpServer
Server server = context.getBean(Server.class);
// 启动服务器
server.start();
// 关闭服务器
server.stop();
// 关闭上下文
context.close();
}
}
- 条件装配 @condition @since 4.0
//步骤一:自定义注解
@Target({ElementType.METHOD}) // 只能标注在方法上面
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnSystemPropertyCondition.class)
public @interface ConditionalOnSystemProperty {
/**
* @return System 属性名称
*/
String name();
/**
* @return System 属性值
*/
String value();
}
//步骤二:添加conditional判断
public class OnSystemPropertyCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 获取 ConditionalOnSystemProperty 所有的属性方法值
MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(ConditionalOnSystemProperty.class.getName());
// 获取 ConditionalOnSystemProperty#name() 方法值(单值)
String propertyName = (String) attributes.getFirst("name");
// 获取 ConditionalOnSystemProperty#value() 方法值(单值)
String propertyValue = (String) attributes.getFirst("value");
// 获取 系统属性值
String systemPropertyValue = System.getProperty(propertyName);
// 比较 系统属性值 与 ConditionalOnSystemProperty#value() 方法值 是否相等
if (Objects.equals(systemPropertyValue, propertyValue)) {
System.out.printf("系统属性[名称 : %s] 找到匹配值 : %s\n",propertyName,propertyValue);
return true;
}
return false;
}
}
//步骤三:配置 @Configuration 类
@Configuration
public class ConditionalMessageConfiguration {
@ConditionalOnSystemProperty(name = "language", value = "Chinese")
@Bean("message") // Bean 名称 "message" 的中文消息
public String chineseMessage() {
return "你好,世界";
}
@ConditionalOnSystemProperty(name = "language", value = "English")
@Bean("message") // Bean 名称 "message" 的英文消息
public String englishMessage() {
return "Hello,World";
}
}
public class ConditionalOnSystemPropertyBootstrap {
public static void main(String[] args) {
// 设置 System Property language = Chinese
System.setProperty("language", "Chinese");
// 构建 Annotation 配置驱动 Spring 上下文
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 注册 配置Bean ConditionalMessageConfiguration 到 Spring 上下文
context.register(ConditionalMessageConfiguration.class);
// 启动上下文
context.refresh();
// 获取名称为 "message" Bean 对象
String message = context.getBean("message", String.class);
// 输出 message 内容
System.out.printf("\"message\" Bean 对象 : %s\n", message);
context.close();
}
}
- 自动装配
底层装配技术
- spring模式注解装配
- spring
@Enable
模块装配- spring条件装配
- spring工厂加载机制
- 实现类:SpringFactoriesLoader
- 配置资源:META-INT/spring.factories
实现方式:
1.激活自动装配@EnableAutoConfiguration
2.实现自动装配xxxAutoConfiguration
3.配置自动装配实现META-INT/spring.factories
15.索引失效场景
例如:一张USER表 有字段属性 name,age 其中name为索引
下面列举几个索引失效的情况
- select * from USER where name=‘xzz’ or age=16;
例如这种情况:当语句中带有or的时候 即使有索引也会失效。
- 2.select * from USER where name like‘%xzz’ ;
例如这种情况:当语句索引 like 带%的时候索引失效(注意:如果上句为 like‘xzz’此时索引是生效的)
- 3.select * from USER where name=123;(此处只是简单做个例子,实际场景中一般name不会为数字的)
例如这种情况:如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
- 4.如果mysql估计使用全表扫描要比使用索引快,则不使用索引(这个不知道咋举例子了 )
- 5.假如上述将name和age设置为联合索引,一定要注意顺序,mysql联合所以有最左原则,下面以name,age的顺序讲下
(1)select * from USER where name=‘xzz’ and age =11;
(2)select * from USER where age=11 and name=‘xzz’;
例如上诉两种情况:以name,age顺序为联合索引,(1)索引是生效的,(2)索引是失效的
总结起来就5点吧:
1.索引不存储null值
2.不适合键值较少的列(重复数据较多的列)
3.前导模糊查询不能利用索引(like '%XX'或者like '%XX%')
4.索引失效的几种情况
5.MySQL主要提供2种方式的索引:B-Tree索引,Hash索引
查看文章 MySQL索引失效的几种情况
网友评论