获得徽章 1
- #青训营笔记创作活动#
2月6日 打卡day26 今日学习:缓存和数据库不一致性问题 1. 对于缓存:读多写少的数据应该放入缓存,但是缓存会带来缓存与数据库双写不一致、缓存雪崩、缓存穿透、缓存并发竞争的问题 2. 缓存与数据库的一致性问题:我们更新数据库的时候需要考虑是否更新缓存,更新缓存消耗性能,在访问次数少的情况下会造成性能浪费,所以不考虑;如果先删除缓存,在无高并发的情况下可以保持数据一致性,在高并发的情况下还是选择后删除缓存,因为达成这个数据不一致性的条件明显会比起其他的方式更为困难。 3. 延迟双删展开评论点赞 - #青训营笔记创作活动#
2月5日 打卡day25 今日学习:缓存 缓存的使用场景:降低自身CPU消耗、减少对外IO交互、提升用户个性化体验 业务与缓存的集成模式:旁路型、穿透型、异步型 优秀实践:可删除重建、有兜底屏障、关注缓存的一致性保证评论点赞 - #青训营笔记创作活动#
2月4日 打卡day24 今日学习:高并发下秒杀商品,你必须知道的9个细节 1. 瞬时高并发:解决方案是页面静态化、CDN加速、缓存、mq异步处理、限流、分布式锁 2. 页面静态化:活动页面绝大多数内容是固定的,为了减少不必要的服务端请求,通常情况下,会对活动页面做`静态化`处理。 3. CDN加速:CDN内容分发网络使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。 4. 秒杀按钮的实现:用js控制,提前缓存到CDN上。开始前js标志为false,开始时系统生成新的js文件,标志为true。用随机参数生成一个新值并同步给CDN,于是CDN不会缓存,每次都能从CDN中获取最新的js代码。 5. 读多写少:redis,部署多个节点。 6. 缓存问题:缓存击穿(加分布式锁、预热)、缓存穿透(缓存更新少用布隆、更新多设置超时时间) 7. 库存问题:预扣库存、回退库存;数据库扣库存(可能系统雪崩)、redis扣库存(incr,会导致结果小于0)、lua脚本 8. 分布式锁:用set指定多个参数、加锁不用setnx 9. mq异步处理:消息丢失问题(加一张消息发送表)、重复消费(加一张消息处理表)、垃圾消息问题(job重试时先判断消息发送表中该消息的发送次数是否达到最大限制)、延迟消费(延迟队列) 10. 限流:对同一用户限流、对同一ip限流、对接口限流、加验证码、提高业务门槛展开评论点赞 - #青训营笔记创作活动#
2月3日 打卡day23 今日学习:为什么用公钥加密却不能用公钥解密? 1. 大数取模运算是不可逆的,因此他人无法暴力解密。但是结合欧拉定理,我们可以选取出合适的p(公钥), q(私钥), N(用于取模的大数),让原本不可逆的运算在**特定情况**下,变得有那么点“可逆”的味道。数学原理决定了我们用公钥加密的数据,只有私钥能解密。反过来,用私钥加密的数据,也只有公钥能解密。 2. HTTPS相当于HTTP+TLS,目前主流的是TLS1.2,基于TCP三次握手之后,再来TLS四次握手。 3. TLS四次握手的过程中涉及到两对私钥和公钥。分别是服务器本身的私钥和公钥,以及CA的私钥和公钥。 4. TLS四次握手背起来会挺难受的,建议关注三个随机数的流向,以此作为基础去理解,大概就能记下来了。展开评论点赞 - #青训营笔记创作活动#
2月2日 打卡day22 今日学习:刨根问底 Redis, 面试过程真好使 一共三十个问题,记录一下不太了解的部分 1. String类型的实现原理:底层实现了简单动态字符串的类型(Simple Dynamic String,SDS),好处是避免缓冲区移除、获取字符串长度的复杂度较低、减少内存分配次数。 2. 内存优化:尽可能使用hash表,因为存储效率高,如果不需要push/pop可以使用;根据业务场景,考虑使用 BitMap;充分利用共享对象池;合理使用内存回收策略。 3. 如何使用分布式锁:INCR、SETNX、SET 4. 同步机制:增量同步(主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令)、全量同步(Slave 初始化时它会发送一个 `psync` 命令到主服务器,如果是第一次同步,主服务器会做一次`bgsave`,并同时将后续的修改操作记录到内存 buffer 中,待 `bgsave` 完成后再将 RDB 文件全量同步到从服务器从服务器接收完成后会将 RDB 快照加载到内存然后写入到本地磁盘,处理完成后,再通知主服务器将期间修改的操作记录同步到复制节点进行重放) 5. 生产问题:缓存穿透(缓存空对象、布隆)、缓存击穿(热点数据不过期、互斥锁更新、随机退避)、缓存雪崩(限流、reload、设置不同过期时间、二级缓存) 6. pipline管道:解决网络延迟,客户端可以一次性发送多个命令无需等待服务端返回;基于队列实现;默认同步个数53个;集群不能使用 7. 性能优化:Master 最好不要做 RDB 持久化展开评论点赞 - #青训营笔记创作活动#
2月1日 打卡day21 今日学习:(四)MySQL之索引初识篇:索引机制、索引分类、索引使用与管理综述 1. 索引机制:①mysql索引的创建方式有:CREATE语句创建、ALTER语句创建、建表时DDL语句创建;②查:SHOW INDEX FROM tableName;删:DROP INDEX indexName ON tableName;指定:`FORCE INDEX`关键字; 2. 索引分类:①字段数量层次:单列索引(唯一、主键、普通)和多列索引(组合索引、联合索引、复合索引)②功能逻辑层次:普通索引、唯一索引、主键索引,MySQL5.7之后增加了全文索引、空间索引,都只有MYISAM支持③存储方式层次:聚簇索引、非聚簇索引 3. 其他索引的创建使用方式展开评论点赞 - #青训营笔记创作活动#
1月31日 打卡day20 今日学习:(五)MySQL索引应用篇:建立索引的正确姿势与使用索引的最佳指南! 1. 索引优劣:主键索引以聚簇的形式存在磁盘中,如果不是顺序性则插入和删除时会调整B+树的结构,导致在索引上的性能开销比较大;要使用联合索引必须包含联合索引的第一个字段;前缀索引无法完成`ORDER BY、GROUP BY`等分组排序工作;全文索引基于分词实现,因此全文索引的文件会额外的大,且修改时也比较耗时;唯一索引虽然查询快,但是插入慢;哈希索引的致命问题在于无序。 2. 正确建立索引:经常频繁用作查询条件的字段应为其创建索引;表的主外键或连表字段,必须建立索引;建立索引的字段,一般值的区分性要足够高;建立索引的字段值不应该过长;建立联合索引应遵循最左前缀原则;经常根据范围取值、排序、分组的字段应建立索引;对于唯一索引,如果不会利用该字段排序,那可以将结构改为`Hash`结构;尽量使用联合索引代替单值索引。 3. 防止索引失效:避免* 、避免在索引列上计算、遵守最左前缀匹配原则、like后面不要前置%、or前后要都建立索引。 4. 索引覆盖:要查询的列,在使用的索引中已经包含,被所使用的索引覆盖。 5. 索引下推:`MySQL5.6`版本以后引入,也就是将`Server`层筛选数据的工作,下推到引擎层处理,减少回表查询次数。 6. MRR机制:会将辅助索引中查询出的`ID`放到缓冲区的`read_rnd_buffer`中,等全部的索引检索工作完成后,或者缓冲区中的数据达到`read_rnd_buffer_size`大小时,对缓冲区中的数据排序,从而得到一个有序的`ID`集合:`rest_sort`,最终再根据顺序`IO`去聚簇/主键索引中回表查询数据。 7. Index Skip Scan索引跳跃式扫描展开评论点赞 - #青训营笔记创作活动#
1月30日 打卡day19
今日学习:数据库管理平台
Bytebase是一款面向开发者的数据库变更管理工具,目前在Github上已有3.6K+Star。
它的主要特性如下:
* SQL审核:具有一站式SQL审核面板,可以直观地看到数据库所有变更记录。
* SQL建议:能自动检查SQL语句规范,额外提供GitHub Action和API接入方式。
* SQL编辑器:可以在线管理及查看数据库表,支持语法的自动提示。
* GitOps工作流:支持集成GitHub和GitLab,使用GitOps工作流进行数据库变更。
* 备份恢复:支持自动备份数据库及恢复数据。
展开评论点赞 - #青训营笔记创作活动#
1月29日 打卡day18
今日学习:SQL优化思路
1. 慢查询日志记录慢SQL
2. explain分析SQL的执行计划
3. profile 分析执行耗时
4. Optimizer Trace分析详情
5. 确定问题并采用相应的措施展开评论点赞 - #青训营笔记创作活动#
1月28日 打卡day17
今日学习:一条SQL语句从诞生至结束
一、SQL如何产生
1. 开发者手动编写
2. ORM框架自动生成
二、SQL执行前会经历的过程
1. 为什么需要数据库连接池?
数据库连接池利用了池化技术对数据库连接进行维护,以达到数据库连接复用的目的。
MySQL的连接池主要是为了实现复用线程。
2. SQL执行前会发生的事情
首先,验证客户端用户名密码是否正确:如果错误,抛出1045的错误码和错误信息;
其次,判断MySQL连接池中是否存在空闲线程:如果存在,直接从连接池中分配空闲线程。如果不存在,创建一条新的工作线程;
最后工作线程会查询MySQL的用户权限表,获取当前登录用户的权限信息并授权。
三、SQL语句在数据库中的执行流程
1. 读
①先将SQL发送给SQL接口,SQL接口会对SQL语句进行哈希处理。
②SQL接口在缓存中根据哈希值检索数据,如果缓存中有则直接返回数据。
③缓存中未命中时会将SQL交给解析器,解析器会判断SQL语句是否正确:
错误:抛出1064错误码及相关的语法错误信息。
正确:将SQL语句交给优化器处理,进入第④步。
④优化器根据SQL制定出不同的执行方案,并择选出最优的执行计划。
⑤工作线程根据执行计划,调用存储引擎所提供的API获取数据。
⑥存储引擎根据API调用方的操作,去磁盘中检索数据(索引、表数据....)。
⑦发生磁盘IO后,对于磁盘中符合要求的数据逐条返回给SQL接口。
⑧SQL接口会对所有的结果集进行处理(剔除列、合并数据....)并返回。
2. 写
大致是一样的,区别在于:
②缓存中有则将对应表的所有缓存全部删除。
⑤在执行开始之前,先记录一下undo-log日志和redo-log(prepare状态)日志。
⑥在缓冲区中查找是否存在当前要操作的行记录或表数据(内存中):
存在:
⑦直接对缓冲区中的数据进行写操作。
利用Checkpoint机制刷写到磁盘。
不存在:
⑦根据执行计划,调用存储引擎的API。
⑧发生磁盘IO,对磁盘中的数据做写操作。
⑨写操作完成后,记录bin-log日志,同时将redo-log日志中的记录改为commit状态。
⑩将SQL执行耗时及操作成功的结果返回给SQL接口,再由SQL接口返回给客户端。展开评论点赞