是什么大仙风把你给刮来了🍃?
快来看看有没有你感兴趣的东西,我亲爱的朋友😉。
自动插件(不维护) 此处粘贴Wistia播放器右键获取的视频链接: 解析视频 手动方法 在正在播放的视频上右键 选择“复制链接(Copy link)”。 从链接里找视频 ID 你会看到类似: wvideo=tra6gsm6rl 这里的 tra6gsm6rl 就是视频的 ID。 如果链接里没有,也可以: 打开网页源代码(view source),搜索: hashedId=tra6gsm6rl 打开嵌入页面 在浏览器里访问: http://fast.wistia.net/embed/iframe/ + 视频ID 比如: http://fast.wistia.net/embed/iframe/tra6gsm6rl 找真实视频文件地址 在打开的页面源代码里搜索: 优先找: "type":"original" 然后往下看一行,会有类似: "url":"http://embed.wistia.com/deliveries/xxxxx.bin" 如果没有 original,就找: "type":"hd_mp4_video" 下载视频 把找到的链接复制出来,把后缀从: .bin 改成: .mp4 然后直接打开或下载就行。 转载自:https://gist.github.com/szepeviktor/2a8a3ce8b32e2a67ca416ffd077553c5
微信小程序和后端用户认证交互流程 微信小程序登录的核心流程:小程序拿临时凭证 code → 后端用 code 换 openid → 后端发自己的 JWT 给小程序。下面是整体流程图。 sequenceDiagram participant MP as 微信小程序 participant WX as 微信服务器 participant GW as gateway participant Auth as auth模块 participant User as user-service participant DB as lia_user库 MP->>WX: wx.login() 获取 code WX-->>MP: 返回临时 code MP->>GW: POST /auth/wx-login {code} GW->>Auth: 转发请求 Auth->>WX: code2session(code) WX-->>Auth: 返回 openid + session_key Auth->>User: OpenFeign 查/建用户 User->>DB: 按 openid 查询 DB-->>User: 用户记录(或空) User-->>Auth: 返回 userId Auth->>Auth: 生成 JWT Auth-->>MP: 返回 token + 用户信息 MP->>MP: 存入 Storage 关键点拆解 1. 小程序端拿 code(前端) ...
消息队列通识 为什么需要消息队列 解耦 削峰填谷 异步调用 消息队列如何保持幂等 重复源泉 生产端重发 发送ACK没有回复继续发送 消费端重复 解决方案 唯一消息ID,生产者发送时携带messageId 幂等表 状态机校验 乐观锁 / 版本号 分布式锁 核心原则 消费逻辑天然幂等 为什么需要消息队列 解耦 异步 削峰 消息队列的模型有哪些 点对点模型 发布订阅模型 如何保证消息不丢失 生产端 ack broker 持久化 生产环境副本因子 >= 3 消费端 手动提交 offset 如何保证消息有序 让需要保持有序的消息落到同一个分区 给唯一的key,且key以后不会重复 Kafka保证唯一分区内有序,跨分区无序 RabbitMQ RabbitMQ 如何保证消息不丢失 哪些情况会丢失 publisher -> exchange 生产者确认机制 ack publish-confirm nack publish-confirm ack publish-return 消息失败之后如何处理 回调方法 记录日志 保存到数据库中然后定时重发 exchange -> queue 消息持久化 交换机持久化 队列持久化 消息持久化 queue queue -> consumer 消费者确认机制 RabbitMQ 消息的重复消费问题是如何解决的 重复消费的原因 ...
SpringCloud 问题 springcloud 五大组件 Eureka / nacos Ribbon Feign / dubbo Hystrix / sentinel Zuul/Gateway 服务注册和发现是什么意思,SpringCloud 如何实现服务注册和发现? nacos 和 eureka 的区别? 相同点 服务提供者 注册 服务信息 到 注册中心 服务消费者 定时从 注册中心 拉取 服务消费者 对 服务提供者 进行远程调用 服务提供者 临时实例 采用心跳检查 什么是临时实例? 默认实例都是临时实例 临时实例心跳模式 非临时主动探测 临时实例没有心跳会被剔除 非临时不会被剔除 ephemeral: false 变成非临时实例 非临时实例,nacos会主动询问服务提供者是否存活 不同点 非临时实例 nacos集群AP,如果存在非临时实例,采用CP eureka采用AP nacos还有配置中心 你们项目中负载均衡是如何实现的? Ribbon Ribbon 负载均衡流程 微服务发起请求 Ribbon 从注册中心拉取 根据策略进行转发 Ribbon 负载均衡策略有哪些? RoundRobinRule 简单轮询 WeightedResponseTimeRule 按照权重来选择服务器,响应时间越长,权重越小 RandomRule BestAvailableRule 忽略短路的服务器,选择并发数较低的服务器 RetryRule 重试机制的选择逻辑(基于轮询) AvailabilityFilteringRule 可用性敏感策略。先过滤非健康的,再选择连接数比较小的 ZoneAvoidanceRule 以区域可用的服务器为基础对服务器选择。 如果想自定义负载均衡策略,如何实现? 自己创建类实现 IRule 接口, 再通过配置类或配置文件配置 @Bean IRule 全局生效 NFLoadBalancerRuleClassName 局部生效 什么是服务雪崩?如何解决这个问题? 服务雪崩 一个服务失败,导致整条链路都失败的情形 解决方案 降级(接口) Feign 接口走fallback 熔断(整个服务) Hystix @EnableCircuitBreaker 断路器关闭 - 打开 - 半开 你们的微服务是怎么监控的? skywalking apache顶级项目 问题定位 性能分析 服务关系 服务告警 业务相关 项目中有没有做过限流?怎么做的? 限流情况 ...
集合 为什么数组索引要从 0 开始?从 1 开始不行吗? 回答大纲 数组在内存中是连续存储的,CPU 通过寻址公式访问元素 从 0 开始:a[i]_address = base_address + i * typeSize 从 1 开始:base_address + (i-1) * typeSize,多一次减法 正式回答 数组在内存中是连续存储的,CPU 通过寻址公式来访问指定下标的元素:a[i] 的地址 = 数组首地址 + i * 元素大小。当数组下标从 0 开始时,直接套用上述公式即可计算偏移量;如果下标从 1 开始,则需要先执行 i - 1 再做乘法,多了一次减法运算。虽然单次访问的差异可以忽略不计,但数组通常会出现在循环、遍历等高频访问的场景中,这笔额外开销会被无限放大。这也是 C 语言沿用下来的历史约定,Java 作为一门追求高效的系统级语言,继承了这一设计。 时间复杂度如何计算的? 回答大纲 口诀:常 对 幂 指 阶 常见复杂度 常数复杂度 O(1):不随 n 变化 对数复杂度 O(logN):二分查找、树操作 正式回答 时间复杂度用于衡量算法执行时间随数据规模 n 增长的变化趋势,是大 O 表示法下对最坏情况的抽象描述。常见的大小关系可用口诀"常对幂指阶"来记忆,即 O(1) < O(logN) < O(N) < O(N*logN) < O(N²) < O(2ⁿ) < O(n!),越靠后算法越慢。 ...
2024 到 2025 年这两年,阿里云、腾讯云、网易、科大讯飞,还有各大高校的公共 Docker 镜像站,基本上是一波接一波地关的关、限的限。到了 2026 年,“拉个镜像如渡劫"这句话已经不是玩笑了。 很多人第一反应是骂大厂抠门。但说实话,这事没那么简单。 合规这座山绕不过去 Docker Hub 是个全球开放的社区,任何人都能往上面推镜像,没有人在入口做内容审查。这就意味着里面什么都有——有漏洞的镜像、带恶意软件的镜像,乃至触碰国内监管红线的内容,全都混在里面。 问题在于,只要阿里云的服务器把这些东西同步下来,再转发给用户,阿里云就天然地成了"中间人”。在现行的监管逻辑下,平台不能说"我只是个镜子,内容不是我的"——你提供了传播通道,你就得负责。这种连带风险,没有哪家大厂愿意为一个免费服务去扛。 带宽这笔账算不过来 Docker 镜像这个东西和 npm、pip 那些包依赖有本质的不同——它就是重。一个普通的 Node.js 基础镜像几百 MB 起步,稍微带点 CUDA 或者 PyTorch 环境的,动辄就是好几个 GB。 国内用镜像源的群体又特别杂:开发者、CI/CD 流水线、还有成千上万台家用 NAS——群晖、极空间这些,很多人设置成定时自动更新,24 小时都在跑。这些流量全是公网出口流量,大厂一分钱都收不到,还得自己掏带宽的钱。 原本这种事情算是一种社区口碑投资,但现在各家都在降本增效,这种"纯出血、零转化"的项目,砍起来是毫不手软的。 大厂没有放弃加速,只是换了玩法 阿里云和腾讯云并没有把镜像加速这个能力整个下线,而是把它圈起来了。 现在的逻辑大概是这样的:你如果买了他们的 ECS,在内网环境里拉镜像,依然是快的、免费的。你如果想在公网用,那你得注册账号、开通 ACR(容器镜像服务),生成一个绑定了你身份的专属加速地址。一旦你的账号有异常,随时可以溯源和封禁。 换句话说,大厂的态度变成了:你是我的付费用户,或者至少是实名用户,我可以给你开小灶;你要是想匿名白嫖,那就没有这个服务了。 那现在大家怎么办? 目前社区里摸索出来的路子主要有几条。 一种是去找垂直的合规镜像站,比如开放原子基金会的 AtomHub,但它只收录了三百多个经过安全审计的基础镜像,能找到自己想要的东西的概率不高。还有一些商业和公益混合性质的服务,比如轩辕镜像、毫秒镜像,口碑还行,但也说不准能撑多久。 另一种是去开通阿里云或腾讯云的个人 ACR,拿到专属链接,老老实实实名用。 最彻底的做法,是自己在香港或者新加坡搞一台便宜的 VPS,用 Nginx 或者 Cloudflare Workers 自建一个反向代理,专供自己用,不对外开放。速度有保障,也不怕被人蹭流量拖垮。很多企业内部和有折腾精神的开发者,现在基本都走这条路了。
面试题从互联网各个角落收集而来 谈一谈 Spring IOC 的底层实现? 反射 工厂的价值 设计模式 关键的几个方法 createBeanFactory getBean doGetBean createBean doCreateBean createBeanInstance(getDeclaredConstructor, newInstance)「方案选单」 populateBean flowchart TD A[开始] --> B["createBeanFactory()创建 DefaultListableBeanFactory"] B --> C[加载 BeanDefinition解析 XML/注解] C --> D["getBean(beanName)外部调用入口"] D --> E["doGetBean(beanName)"] E --> F{从缓存获取单例?} F -->|是| G[返回缓存的 Bean] F -->|否| H["createBean(beanName, mbd)"] H --> I["doCreateBean(beanName, mbd)"] I --> J["createBeanInstance()getDeclaredConstructor + newInstance"] J --> K["populateBean()属性填充/依赖注入"] K --> L["initializeBean()初始化回调"] L --> M[注册销毁方法] M --> N[返回完整 Bean 实例] 谈谈 SpringIOC 的理解,原理和实现? IOC 思想 DI 实现手段 什么是容器 什么是Bean BeanDefination 从哪里读 XML 注解 存哪里 所有 BeanDefinition 都存在 DefaultListableBeanFactory 里的一个 Map 中 容器的生命周期 flowchart TD START([🚀 程序启动]) --> REFRESH["AbstractApplicationContext.refresh()"] REFRESH --> PHASE1 subgraph PHASE1["🔵 第一阶段:准备工作"] direction TB A1["prepareRefresh()\n记录启动时间\n设置容器状态为「活跃」\n初始化环境变量"] --> A2 A2["obtainFreshBeanFactory()\n创建 DefaultListableBeanFactory\n这是容器的核心仓库"] --> A3 A3["prepareBeanFactory()\n注册基础 BeanPostProcessor\n注册 Aware 相关处理器\n注册默认环境 Bean(environment)"] end PHASE1 --> PHASE2 subgraph PHASE2["🟢 第二阶段:加载 BeanDefinition(读图纸)"] direction TB B1["扫描 @ComponentScan 指定的包\n或读取 XML 配置文件"] --> B2 B2["解析注解 / XML\n识别 @Component @Service\n@Repository @Controller @Bean"] --> B3 B3["为每个 Bean 生成 BeanDefinition\n记录:类名、作用域、是否懒加载\n初始化方法、销毁方法、依赖关系"] --> B4 B4[("存入 beanDefinitionMap\nkey = beanName\nvalue = BeanDefinition")] end PHASE2 --> PHASE3 subgraph PHASE3["🟡 第三阶段:修改 BeanDefinition(修图纸)"] direction TB C1["invokeBeanFactoryPostProcessors()\n执行所有 BeanFactoryPostProcessor"] --> C2 C2["ConfigurationClassPostProcessor\n处理 @Configuration @Import\n@PropertySource @ComponentScan\n👉 SpringBoot 自动装配在此触发"] --> C3 C3["PropertySourcesPlaceholderConfigurer\n替换 BeanDefinition 中\n所有 ${xxx} 占位符为真实值"] --> C4 C4[/"所有 BeanDefinition 最终确定\n图纸不再变动"/] end PHASE3 --> PHASE4 subgraph PHASE4["🌸 第四阶段:注册 BeanPostProcessor(工人就位)"] direction TB D1["registerBeanPostProcessors()\n按优先级顺序注册\nPriorityOrdered → Ordered → 普通"] --> D2 D2["AutowiredAnnotationBeanPostProcessor\n负责处理 @Autowired @Value"] --> D3 D3["CommonAnnotationBeanPostProcessor\n负责处理 @PostConstruct @PreDestroy @Resource"] --> D4 D4["AnnotationAwareAspectJAutoProxyCreator\n负责检测切面、生成 AOP 代理对象"] --> D5 D5[/"所有工人就位\n等待 Bean 创建时介入\n此时不开工"/] end PHASE4 --> PHASE5 subgraph PHASE5["🟣 第五阶段:容器基础设施初始化"] direction TB E1["initMessageSource()\n初始化国际化资源 i18n"] --> E2 E2["initApplicationEventMulticaster()\n初始化事件广播器"] --> E3 E3["onRefresh()\n⭐ SpringBoot 在此启动\nTomcat / Jetty / Undertow\nWeb 容器开始监听端口"] --> E4 E4["registerListeners()\n注册所有 ApplicationListener\n监听容器事件"] end PHASE5 --> PHASE6 subgraph PHASE6["🟠 第六阶段:实例化所有单例 Bean"] direction TB F1["finishBeanFactoryInitialization()\npreInstantiateSingletons()\n遍历所有非懒加载单例 BeanDefinition"] --> F2 F2["逐个执行 getBean()\n触发每个 Bean 的生命周期\n实例化 → 属性填充 → Aware回调\n→ 前置处理 → init方法 → 后置处理"] --> F3 F3[("所有单例 Bean 存入\nsingletonObjects 一级缓存\n✅ 全部就绪")] end PHASE6 --> PHASE7 subgraph PHASE7["✅ 第七阶段:容器就绪"] direction TB G1["finishRefresh()\n清理启动时占用的资源\n初始化生命周期处理器"] --> G2 G2["发布 ContextRefreshedEvent\n通知所有监听者:容器启动完成"] --> G3 G3[/"容器进入运行状态\n可以处理业务请求"/] end G3 --> RUNNING([🎉 容器正常运行中]) RUNNING -.->|"收到关闭信号\nCtrl+C / kill / close()"| PHASE8 subgraph PHASE8["🔴 第八阶段:容器销毁"] direction TB H1["发布 ContextClosedEvent\n通知所有监听者:容器即将关闭"] --> H2 H2["停止 Web 容器\nTomcat 停止接受新请求"] --> H3 H3["执行所有 Bean 的销毁逻辑\n@PreDestroy → destroy() → destroy-method\n按注册顺序逆序销毁"] --> H4 H4["清空所有缓存\nsingletonObjects 清空\nbeanDefinitionMap 清空"] --> H5 H5["容器状态设置为「关闭」\nactive = false / closed = true"] end H5 --> END([💀 容器销毁完成]) style START fill:#43A047,color:#fff style RUNNING fill:#43A047,color:#fff style END fill:#e53935,color:#fff style REFRESH fill:#1E88E5,color:#fff bean 的生命周期 flowchart TD START([🌱 开始创建 Bean]) --> A A["① 实例化\nInstantiation\n反射调用构造方法\nnew 出空壳对象\n此时所有字段都是 null"] --> B B["② 放入三级缓存\nsingletonFactories\n提前暴露半成品\n为循环依赖做准备"] --> C C["③ 属性填充\npopulateBean()\n处理 @Autowired @Value\n把依赖的 Bean 注入进来"] --> D subgraph AWARE["④ Aware 回调"] direction TB D["BeanNameAware\n告诉 Bean 自己叫什么名字"] --> E E["BeanFactoryAware\n把 BeanFactory 塞给 Bean"] --> F F["ApplicationContextAware\n把 ApplicationContext 塞给 Bean"] end subgraph INIT["⑤ 初始化 initializeBean()"] direction TB G["前置处理\npostProcessBeforeInitialization()\n所有 BeanPostProcessor 挨个执行\n📌 @PostConstruct 在这里被调用"] --> INITMETHOD subgraph INITMETHOD["init 方法(按顺序执行)"] direction TB H1["第1个:@PostConstruct\n(已在前置处理中执行)"] --> H2 H2["第2个:afterPropertiesSet()\n实现 InitializingBean 接口"] --> H3 H3["第3个:init-method\n@Bean(initMethod='xxx') 或 XML 配置"] end INITMETHOD --> I I["后置处理\npostProcessAfterInitialization()\n所有 BeanPostProcessor 挨个执行\n⭐ AOP 代理在这里生成"] end AWARE --> INIT I --> J subgraph CACHE["⑥ 存入缓存"] direction TB J["从三级缓存 singletonFactories 移除\n从二级缓存 earlySingletonObjects 移除"] --> K K["存入一级缓存 singletonObjects\n✅ 完整 Bean 就绪"] end K --> READY([🎉 Bean 可以正常使用了]) READY -.->|"容器关闭"| DESTROY subgraph DESTROY["⑦ 销毁阶段(容器关闭时)"] direction TB D1["第1个:@PreDestroy\n方法被调用"] --> D2 D2["第2个:destroy()\n实现 DisposableBean 接口"] --> D3 D3["第3个:destroy-method\n@Bean(destroyMethod='xxx') 或 XML 配置"] end D3 --> END([💀 Bean 销毁完成]) spring 三级缓存依赖流程 sequenceDiagram participant Spring as Spring容器 participant L3 as 三级缓存singletonFactories participant L2 as 二级缓存earlySingletonObjects participant L1 as 一级缓存singletonObjects Note over Spring: 开始创建 A Spring->>Spring: ① new A 空壳对象 Spring->>L3: ② 存入 A 的 ObjectFactory lambda Note over Spring: 给 A 注入属性,发现需要 B Spring->>Spring: ③ new B 空壳对象 Spring->>L3: ④ 存入 B 的 ObjectFactory lambda Note over Spring: 给 B 注入属性,发现需要 A Spring->>L1: ⑤ getBean(A),查一级缓存 L1-->>Spring: ❌ 没有 Spring->>L2: 查二级缓存 L2-->>Spring: ❌ 没有 Spring->>L3: 查三级缓存 L3-->>Spring: ✅ 找到 A 的 lambda! Spring->>Spring: ⑥ 执行 lambda(需要代理则生成代理 A) Spring->>L2: ⑦ 早期引用放入二级缓存 Spring->>L3: 删除三级缓存中的 A Note over Spring: B 拿到 A 的早期引用,B 完成初始化 Spring->>L1: ⑧ B 放入一级缓存 ✅ Spring->>L3: 删除三级缓存中的 B Note over Spring: 回到 A 的流程,B 已就绪,A 完成初始化 Spring->>L1: ⑨ A 放入一级缓存 ✅ Spring->>L2: 删除二级缓存中的 A Note over L1: 最终:一级缓存中有完整的 A 和 B ✅ 情况 三级缓存 lambda 执行 二级缓存 无循环依赖,无 AOP 存了 lambda ❌ 不执行 不经过 无循环依赖,有 AOP 存了 lambda ❌ 不执行 不经过 有循环依赖,无 AOP 存了 lambda ✅ 执行 存原始对象 有循环依赖,有 AOP 存了 lambda ✅ 执行 存代理对象 spring bean 缓存的放置时间和删除时间 Spring Bean 三级缓存的放置与删除时间 缓存 存的是什么 放入时机 删除时机 三级 singletonFactories Bean 的工厂 lambda 实例化完成后立刻放入 工厂被调用时(升级到二级)或 Bean 完成时 二级 earlySingletonObjects 早期暴露的半成品 Bean 三级工厂被调用的瞬间 Bean 完全初始化完成放入一级时 一级 singletonObjects 完整可用的 Bean 初始化全部完成后 容器关闭销毁时 BeanFactory 和 FactoryBean 的区别? FactoryBean 是什么 public interface FactoryBean<T> { // 返回 Bean 的实例(可以是复杂创建逻辑) T getObject() throws Exception; // 返回 Bean 的类型 Class<?> getObjectType(); // 是否单例 default boolean isSingleton() { return true; } } 相同点 都是用来创建Bean对象的 不同点 使用 BeanFactory 创建对象的适合必须遵循严格的生命周期流程,太复杂了。如果想简单自定义某个对象的创建,同时想交给spring管理,那么必须实现 FactoryBean 接口 isSingleton 是否是单例对象 getObjectType 获取返回对象的类型 getObject 自定义创建对象的过程 对比维度 BeanFactory FactoryBean 角色 容器/工厂接口 特殊的 Bean 功能 管理所有 Bean 的生命周期 自定义某个 Bean 的创建逻辑 定位 基础设施(IOC 容器) 业务扩展(创建复杂对象) 使用方式 由 Spring 框架实现和使用 由开发者实现,注册到容器中 常见实现 DefaultListableBeanFactory SqlSessionFactoryBean、ProxyFactoryBean 谁创建谁 BeanFactory 创建并管理 FactoryBean FactoryBean 创建业务对象 flowchart LR subgraph BeanFactory[BeanFactory - IOC容器] direction LR Bean1[普通 Bean] Bean2[普通 Bean] FB[FactoryBean特殊 Bean] end FB -->|调用 getObject| Result[业务对象] User[开发者] -->|getBean| BF[BeanFactory] BF -->|返回| Bean1 BF -->|返回| Bean2 BF -->|返回 getObject 结果| Result BF -->|加 & 前缀| FB Spring中用到的设计模式 单例模式 原型模式(指定作用域为prototype) 工厂模式 BeanFactory 模板方法 JdbcTemplate TransactionTemplate RestTemplate RedisTemplate 策略模式 XmlBeanDefinitionReader PropertiesBeanDefinitionReader 观察者模式 listener event multicast 适配器模式 HandlerAdapter 装饰者模式 BeanWrapper 责任链模式 使用aop的时候会先生成一个拦截器链 SpringMVC 的filter责任链 代理模式 动态代理 委托者模式 delegate Spring AOP 底层实现原理 🥇 第一层:一句话定性(开场) “Spring AOP 的底层本质是动态代理。Spring 在容器初始化 Bean 的时候,通过 BeanPostProcessor 机制拦截,判断这个 Bean 是否需要被增强,如果需要,就用动态代理生成一个代理对象,替换掉原始 Bean 注册进容器。后续所有对这个 Bean 的调用,实际上都是在走代理对象。” ...
我目前使用的电钢琴是卡哇伊(KAWAI)ES105(据网友称为未阉割半踏版本)。今天路过南京一家琴行,顺便试弹了四款电钢琴: ROLAND FP30X YAMAHA P-125 KAWAI CA-30 ROLAND HP704 一、整体第一印象:差异主要在音响,而非键盘 试弹四款琴后,我的第一感受是: 它们之间最大的差异并不在键盘手感,而是在外放音质。 1)外放音质对比 YAMAHA P-125 整体音质最弱(但仍在“可用可听”范围内)。 主要问题是低频明显不足,声音偏薄,但不至于刺耳或难以接受。 ROLAND HP704 外放表现最好。低频量感更足,整体更饱满。 但说实话,它并没有带来那种“震撼级”的听感提升。 一个有意思的对比是: 如果让我用索尼 N3AP 监听耳机接在我的 KAWAI ES105 上 vs HP704 外放,我反而会更倾向前者的听感。 二、键盘手感体验:FP30X 最接近立式钢琴 1)整体结论 在四款琴中: ROLAND FP30X 的键盘手感最接近立式钢琴。 但它和真正立式钢琴的关键差异在于: 琴键整体“偏轻” 2)关于“键盘力度”的感受 我个人认为琴键的力度对演奏表现影响非常大,它类似于摄影中的“动态范围”概念: 力度越真实、越重 → 越容易表达音乐的“张力”和“重量感” 过轻的键盘 → 更容易弹,但表现力上限受限 在老师的立式钢琴上弹奏时,我能明显感觉到: 木质机械结构带来的“阻尼感” 以及它对音乐表现力的客观增强 3)关于日系 vs 欧系键盘重量的观察 常见说法是: 欧系键盘更重 日系键盘更轻 我认为这可能与欧洲古典音乐对“力度层次”和“表现张力”的需求有关。 不过轻键盘也有优势: 回弹更快 更适合轮指、快速技巧类乐段 三、市场选择逻辑:为什么 FP30X 卖得好 琴行老师提到: FP30X 是卖得最好的型号之一 我理解原因如下: 手感更接近立式钢琴 琴童在家练习后,上课用真钢琴“割裂感更小” 不容易出现“换琴就不跟手”的问题 从实用角度看,这种一致性非常关键。 ...
面试题从互联网各个角落收集而来 如何定位慢查询? 方案1 开源工具 Arthas 运维工具 Prometheus Skywalking 方案2 MySQL自带慢日志(mysql性能损耗) 开启慢日志方法 /etc/my.conf slow_query_log long_query_time SQL语句执行很慢,如何分析 慢的原因 聚合查询 多表查询 表数据量过大查询 深度分页查询 如何分析慢 explain, desc 命令 如何分析执行结果? extra 的额外优化建议 using where; using index 查找使用了索引,需要的数据在索引列都能找到,不需要回表查询数据 using index condition 查找使用了索引 type index,all 需要优化 了解过索引吗?什么是索引? 索引(index)是帮助 MySQL 高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构(如 B+ 树),这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。 帮助MySQL高效获取数据的数据结构 索引的底层数据结构了解过吗? 二叉搜索树 红黑树 B树 B+树 阶数更多,路径更短 磁盘读写代价B+树更低,叶子节点才能真正存储数据 便于扫库和区间查询,叶子节点是双向链表 什么是聚簇索引?什么是非聚簇索引? 聚簇索引 二级索引 什么是回表查询? 知道什么是覆盖索引吗? 通过该索引查询能够一次找到所有数据,且无需回表的,就是覆盖索引 MySQL超大分页怎么处理? 使用覆盖索引加上子查询 select * from tb_sku t, (select id from tb_sku order by id limit 9000000,10) a where t.id = a.id 索引创建的原则有哪些? 单表超过10万条数据且查询比较频繁的表建立索引 常常作为查询条件的字段要建立索引 使用区分度高的列作为索引,尽量建立唯一索引 字符串类型的字段长度较长可以建立前缀索引 尽量使用联合索引,减少单列索引 索引列使用NOT NULL方便优化器确定哪个索引更好用于查询 什么情况下索引会失效? 违反了最左前缀法则 查询范围右边的列,不能使用索引 索引列上进行运算操作,索引列失效 字符串不加单引号,索引失效(索引类型转换导致的失效) 字符串非尾部匹配,索引失效 谈一谈对SQL优化的经验 表设计优化 我们参考了 阿里开发手册《嵩山版》 根据实际存储数值长短设计数据类型 索引的优化 SQL语句的优化 select 语句务必指明字段名称 为了覆盖索引 尽量用 union all 代替 union 避免对 where 子句中对字段进行表达式操作 能用 innerjoin 就不用 left join , right join。如必须,要以小表为驱动 主从复制,读写分离 分库分表 事务的特性详细说一说 并发事务带来哪些问题,如何解决这些问题?MySQL的默认隔离级别是? 并发事务的问题 脏读 读已提交 不可重复读 值问题 可重复读 幻读 数量问题 串行化 隔离级别 未提交读 读已提交 可重复读* 串行化 undo log 和 redo log 的区别 缓冲池 数据页 redo log 物理 持久 undo log 逻辑 原子 一致 事务的隔离性底层是如何保证的? 锁:排他锁 MVCC 多版本并发控制 依赖于 隐式字段 DB_TRX_ID DB_ROLL_PTR DB_ROW_ID undo log 版本链 版本链数据访问规则 readview 快照读 Read Committed 每次 select都生成一个快照读 Repeatable Read 开启事务后第一个 select 语句才是快照读的地方 核心字段 m_ids min_trx_id max_trx_id creator_trx_id RC隔离级别下,在事务中每次执行快照读时生成 ReadView MySQL 的主从同步原理 核心:二进制日志 BINLOG DDL DML 主数据库在事务提交时,变更记录写入 Binlog 从库 binlog -> 中继日志 从库 中继日志读取事件 -> 从库数据库 你们项目用过分库分表吗? 什么时候分库分表 单表数据量达到1000W 或者 20GB 优化解决不了性能问题 IO、CPU瓶颈 如何拆分 垂直拆分 垂直分库 不同表拆分到不同库 适用于微服务 垂直分表 不常用字段单独放在一张表 水平拆分 水平分库 一个库的数据拆分到多个库中 路由规则 根据id节点取模 按id范围路由 水平分表 一个表的数据拆分到多个表中 新的问题 分布式事务一致性问题 跨节点关联查询 跨节点分页、排序函数 主键去重 解决方案 分库分表中间件 mycat sharding-sphere 深入问题 为什么 InnoDB 主键建议自增? 为什么非自增主键会导致页分裂? 为什么 MyISAM 和 InnoDB 索引结构不同? 为什么 B+树适合磁盘而红黑树不适合?