一些可以参考的文档集合3
20211021一篇带你用 VuePress + Github Pages 搭建博客前言最近完成了 TypeScript 最新官方文档 Hanbook 的翻译,一共十四篇,堪称国内的最好 TypeScript4 入门教程之一。为了方便大家阅读,我用 VuePress + Github Pages 搭建了博客,博客效果如下:博客地址如下:Githubhttps://mqyqingfeng.githu
20220419
java18 向量API
https://openjdk.java.net/jeps/417https://openjdk.java.net/jeps/417
java虚拟线程用户级线程
JEP 425: Virtual Threads (Preview)https://openjdk.java.net/jeps/425
20220415
如何查找泄露的全局变量
20220414
无论语言层面何种并发模型,到了操作系统层面,一定是以线程的形态存在的。
Go线程实现模型MPG
M指的是Machine,一个M直接关联了一个内核线程。P指的是”processor”,代表了M所需的上下文环境,也是处理用户级代码逻辑的处理器。G指的是Goroutine,其实本质上也是一种轻量级的线程。
这个图讲的是两个线程(内核线程)的情况。一个M会对应一个内核线程,一个M也会连接一个上下文P,一个上下文P相当于一个“处理器”,一个上下文连接一个或者多个Goroutine。P(Processor)的数量是在启动时被设置为环境变量GOMAXPROCS的值,或者通过运行时调用函数runtime.GOMAXPROCS()进行设置。Processor数量固定意味着任意时刻只有固定数量的线程在运行go代码。Goroutine中就是我们要执行并发的代码。图中P正在执行的Goroutine为蓝色的;处于待执行状态的Goroutine为灰色的,灰色的Goroutine形成了一个队列runqueues。
三者关系的宏观的图为:
当其中一个Goroutine 发生了系统调用sysall,Goroutine 关联的M需要放弃当前的上下文环境P,让别的M接管当前的P,以便可以让其他的Goroutine被调度执行。
M0中的G0执行了syscall,然后就创建了一个M1(也有可能本身就存在,没创建),(转向右图)然后M0丢弃了P,等待syscall的返回值,M1接受了P,将继续执行Goroutine队列中的其他Goroutine。
20220413
协程分为无栈协程和有栈协程两种,无栈指可挂起/恢复的函数,有栈协程则相当于用户态线程。有栈协程切换的成本是用户态线程切换的成本,而无栈协程切换的成本则相当于函数调用的成本。
无栈协程和线程的区别:无栈协程只能被线程调用,本身并不抢占内核调度,而线程则可抢占内核调度。
协程这种相互协作调度的思想和 top-down 是不合的,在协程中各个模块之间存在很大的耦合关系,并不符合高内聚低耦合的编程思想,相比之下 top-down 使程序结构清晰、层次调度明确,代码可读性和维护性都很不错。
与线程相比,协作式任务系统让调用者自己来决定什么时候让出,比操作系统的抢占式调度所需要的时间代价要小很多,后者为了能恢复现场会在切换线程时保存相当多的状态,并且会非常频繁地进行切换,资源消耗更大。
综合来说,协程完全是用户态的行为,由程序员自己决定什么时候让出控制权,保存现场和切换恢复使用的资源也非常少,同时对提高处理器效率来说也是完全符合的。
工作 6 年多,我还是没有搞懂什么是协程的道与术工作 6 年了,还是没搞懂协程https://mp.weixin.qq.com/s/SBDntpy5lE2SHV4I1F4Lfw
20220410
Go 语言设计者 Robert Griesemer 深入介绍泛型Go 官方博客近日发表了一篇介绍新特性“泛型”的文章,作者是两位重量级人物 —— Robert Griesehttps://mp.weixin.qq.com/s/AGLq2va5b9vSPdo1MuY6lwhttps://mp.weixin.qq.com/s/YikGX5zj5Qzl4_i91ZZUHgGo 语言设计者 Robert Griesemer 深入介绍泛型golang本地缓存(bigcache/freecache/fastcache等)选型对比及原理总结提到本地缓存大家都不陌生,只要是个有点经验的后台开发人员,都知道缓存的作用和弊端。本篇文章我们就来简单聊聊在golang做业务开发的过程中,本地缓存的一些可选的开源方案。分析它们的特点,以及内部的实现原理https://mp.weixin.qq.com/s/YikGX5zj5Qzl4_i91ZZUHg
20220407
浏览器的本地文件访问API
20220406
Beej's Guide to C Programminghttps://beej.us/guide/bgc/
INPLACE 和 Online 是两个不同维度的事情。COPY 和 INPLACE 指的是 DDL 内部的执行逻辑,可以简单的理解成:COPY 是在 Server 层的操作,INPLACE 是在 InnoDB 层的操作。而用户更加关心 Online 与否,通常只与一个问题有关:是否允许并发 DML。两个基本结论:
- COPY 算法执行的 DDL 肯定不是 Online 的;
- INPLACE 算法执行的 DDL 不一定是 Online 的
INSTANT DDL 是 MySQL 8.0 引入的新功能,当前支持的范围较小,包括:
- 修改二级索引类型
- 新增列
- 修改列默认值
- 修改列 ENUM 值
- 重命名表
在执行 DDL 操作时,MySQL 内部对于 ALGORITHM 的选择策略是:如果用户显式指定了 ALGORITHM,那么使用用户指定的选项;如果用户未指定,那么如果该操作支持 INPLACE 则优先选择 INPLACE,否则选择 COPY;当前不支持 INPLACE 的操作主要有:
- 删除主键
- 修改列数据类型
- 修改表字符集
我们常说的 Online DDL,其实是从 DML 操作的角度描述的,如果 DDL 操作不阻塞 DML 操作,那么这个 DDL 就是 Online 的。当前非 Online 的 DDL 其实已经比较少了,主要有:
- 新增全文索引
- 新增空间索引
- 删除主键
- 修改列数据类型
- 指定表字符集
- 修改表字符集
MySQL · 源码阅读 · 白话Online DDL发展历程http://mysql.taobao.org/monthly/2021/03/06/
直方图与索引的区别
与索引相比,直方图并不能直接加速数据扫描,只是通过辅助选择更优的 where 条件或 join order 来优化执行计划。但由于直方图中储存的数据更为精简,对它进行创建、储存与更新的代价也比索引要小得多。同时,直方图不要求与表中数据保持实时同步,只需要在表中数据已经累计的较多修改是手动更新即可。所以直方图也完全不会对insert及delete的效率造成影响。
serializable以下的隔离级别,是以牺牲一定的一致性和隔离性来换取数据库执行事务并发度的提高。明确的隔离级别的定义就是告诉用户,数据库在对应的隔离级别下能作出那些保证,”满足用户预期的不正确何尝不是一种正确呢?”
两阶段锁协议内容如下:
阶段一(Growing):事务向锁管理器申请所需要的锁,锁管理器分配或拒绝对应的锁。
阶段二(Shrinking):事务释放在Growing阶段申请的锁,并不能再申请新的锁。
多粒度锁
截止目前,我们所讲的锁都指的是tuple级别的,也就是我们通常所说的行锁。我们知道数据库中数据管理的粒度从上到下有database、table、tuple、column。一般来说数据库操作的最小单位是行,所以最小粒度的锁也就是行锁。那么行锁释放可以满足所有场景的加锁需求呢?
事务T1要访问整个数据库,数据库中有几十亿条数据项,如果给其中的每一个数据项都加锁,那么加锁的代价是不可接受的。如果T1能够只发出一个封锁整个数据库的加锁请求,那么加锁的代价就很低了。另外一方面如果事务T1只访问少量的数据项,就不应该给整个数据库加锁,因为会限制整体的并发性。
因此为了满足不同场景的加锁需求,需要一种允许系统定义多级粒度锁的机制。整体多级粒度锁的关系是如下图的树状的结构,树中的每个节点都可以单独加锁。当事务对一个节点加锁(共享锁或排他锁)时,该事务隐式的给这个节点的所有后代节点加上了同类型的锁。层次越高的锁,整体加锁和释放锁的代价越低,但是会限制整体的并发度;层次越低的锁,整体加锁和释放锁的代价越高,但是有利于并发。
意向锁
假设事务T1希望对整个数据库加排他锁,也就是对root节点加排他锁,那么锁管理器需要确认这个加锁请求能否成功。为此,锁管理器需要遍历整个树状层次结构的所有节点,如果所有节点都没持有锁,那么可以对root节点加排他锁,否则需要延迟或拒绝该加锁请求。遍历整个层级结构的所有节点去判断能够加锁成功,这种方式不符合了多粒度锁的初衷,因为检查所有节点是否加锁跟直接对所有节点加锁的代价可以认为是相同的(最起码是一个数量级的)。
为了解决上述问题,引入了一种新的锁类型-意向锁。如果一个节点加了意向锁,则意味着要在其后代节点进行显式加锁。在一个节点显式加锁之前,该节点的全部祖先节点均加上了意向锁。因此,判定能够成功给一个节点加锁时不必搜索整棵树。给某个节点加锁的事务必须遍历从root节点到该节点的路径,并给路径上的各节点加上意向锁。
意向锁相当于是一个提前的加锁声明。这样其他事务就可以根据节点上的意向锁类型来判断它的加锁请求能否成功。为了达到这个目的要求,对某个节点显式的加共享锁或排他锁之前,必须对root节点到该节点的路径上的其他节点加相应的意向锁。通过意向锁,事务可以在一个高的层次上去加共享锁或排他锁,而不需要去检查所有的后代节点的加锁情况。
inno_space 是一个可以直接访问InnoDB 内部文件的命令行工具, 可以打印出文件的内部结构.
Jeremy Cole 用ruby 写了一个类似的工具, 不过不支持MySQL 8.0, 并且ruby 编译以及改动起来特别麻烦, 所以用cpp 重写了一个. inno_space 做到不依赖任何外部文件, 只需要make, 就可以得到可执行文件, 做到开箱即用.
inno_space 除了支持打印出文件的具体结构之外, 同时还支持修复 corrupt page 功能, 如果遇到InnoDB 表文件中的page 损坏, 实例无法启动的情况, 如果损坏的只是leaf page, inno_space 可以将corrupt page 跳过, 从而保证实例能够启动, 并且将绝大部分的数据找回.
MySQL · 周边工具 · MySQL InnoDB inno_space 工具介绍什么是inno_space?http://mysql.taobao.org/monthly/2021/11/02/
- 脏读(Dirty Read): 读到了其他事务还未提交的数据;
- 不可重复读(Non-Repeatable/Fuzzy Read):由于其他事务的修改或删除,对某数据的两次读取结果不同;
- 幻读(Phantom Read):由于其他事务的修改,增加或删除,导致Range的结果失效(如where 条件查询)
- 在操作甚至是事务开始之前就检测冲突的基于Lock的方式;
- 在操作真正写数据的时候检测的基于Timestamp的方式;
- 在事务Commit时才检测的基于Validation的方式
这三种策略的立足点其实是对冲突的乐观程度,越乐观,也就是认为冲突发生越少,就越倾向于推迟冲突的检测。直观的也可以看出,越晚的冲突检测越有可能获得高的并发。但当冲突真正出现时,由于前面的操作可能都需要一笔勾销,因此在冲突较多的场景下,太乐观反而得不偿失。而冲突归根结底是由用户的使用场景决定的,在不能对用户场景做太多假设的通用数据库中,毫无疑问,基于Lock的方式显得更为合适。除此之外,由于MVCC的广泛应用消除了读写之间的冲突,使得Lock带来的并发影响大大降低,也使得基于Lock的并发控制仍然是主流。 对数据库的数据加锁这件事情,本身是跟数据的组织方式是密不可分的,数据组织方式可能给加锁带来限制,同时利用组织方式的特性,可能也能改造和优化加锁过程
DataBase · 理论基础 · B+树数据库加锁历史前言:http://mysql.taobao.org/monthly/2022/01/01/
volatile 为什么能保证内存数据的可见性,一般用于标识字段比如 开关,是否初始化等
volatile提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。
perf 是Linux的一款性能分析工具,能够进行函数级和指令级的热点查找,可以用来分析程序中热点函数的CPU占用率,从而定位性能瓶颈。
Performance analysis tools for Linux.
系统性能分析工具:perf - 知乎perf 是Linux的一款性能分析工具,能够进行函数级和指令级的热点查找,可以用来分析程序中热点函数的CPU占用率,从而定位性能瓶颈。 Performance analysis tools for Linux.系统性能优化通常可以分为两个阶段:性…https://zhuanlan.zhihu.com/p/186208907故障分析 | MySQL 异地从库复制延迟案例一则作者:任坤 现居珠海,先后担任专职 Oracle 和 MySQL DBA,现在主要负责 MySQL、mongoDB 和 Redis 维护工作。 本文来源:原创投稿 *爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。 1、背景 线上某核心 MySQL ,版本为 5.6,本地机房1主2从,同时部署了一个异地从库。 从2月14号起异地...https://opensource.actionsky.com/20220228-mysql/
终于有大佬把"计算机底层原理"全部总结出来了 - 文章详情https://z.itpub.net/article/detail/2B71CE9B637BBC0AF8447E377D2732B5
20220404
20220402
并发数据一致性通常实现: 锁 + 多数据版本
提高并发读的思路: 通过共享锁保证读读并发,独占锁实现读写互斥
提高并发读写的思路: 一致性折衷,通过数据多版本控制,读使用快照版本,读写不互斥,提高读写并发能力
20220401
操作系统导论 线程的内存布局空间
马尔科夫链
马尔可夫链是从一个“状态”(一种情况或一组值)跳到另一个“状态”的数学系统。例如,如果您制作了婴儿行为的马尔可夫链模型,您可能会将“玩耍”、“吃饭”、“睡觉”和“哭泣”作为状态,它们与其他行为一起可以形成“状态空间”:所有可能状态的列表。此外,在状态空间之上,马尔可夫链告诉您从一个状态跳跃或“转换”到任何其他状态的概率——例如,正在玩耍的婴儿在下一个状态下入睡的可能性五分钟不先哭。
Markov Chainshttps://setosa.io/blog/2014/07/26/markov-chains/
20220331
20220330
20220327
如何优雅地给对象的所有方法添加异常处理Proxy 在异常处理的应用https://mp.weixin.qq.com/s/hehUH9HL6unaLWq3LzQxNg
分享小技巧:实现在浏览器中import内联JS模块https://mp.weixin.qq.com/s/ghWlsNLu1JhnoiC7oouv8g
babel-从入门到上手本文将引导你一步一步的学会babel的插件自定义https://mp.weixin.qq.com/s/LlQRx5SPmFgnTDO8VunGnw
从 chromium 源码来窥探浏览器的渲染这题太难了https://mp.weixin.qq.com/s/r1nAcEkEoE1D7CgQwqSe2Q
手写简易前端框架:vdom 渲染和 jsx 编译一步步实现一个前端框架https://mp.weixin.qq.com/s/xwt5bd31IZChpEx79w5E5g
20220325
markdown canddy
20220322
打印java jvm 所用参数
-XX:+PrintCommandLineFlags
打印出
-XX:ConcGCThreads=2 -XX:G1ConcRefinementThreads=6 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=2147483648 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=4294967296 -XX:MinHeapSize=2147483648 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+ShowCodeDetailsInExceptionMessages -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC -XX:-UseLargePagesIndividualAllocation
JDK 17 中的 ZGC 远低于其亚毫秒级暂停时间的目标。G1 的目标是在延迟和吞吐量之间保持平衡,远低于其默认的 200 毫秒暂停时间目标。
ZGC 被设计为具有不随堆大小扩展的暂停时间,我们清楚地看到当堆扩大到 128 GB 时就是这种情况。从暂停时间的角度来看,G1 比 Parallel 更好地处理更大的堆,因为它具有保持暂停时间目标的逻辑。
总结
与旧版本相比,JDK 17的整体性能要好得多,无论您使用哪种收集器。如果您仍在使用 JDK 8 并计划升级,那么现在可能是重新评估要使用的 GC的好时机。在 JDK 8 Parallel 是默认设置,但在 JDK 9 中更改为 G1。从那时起,G1 以比 Parallel 更高的速度改进,但仍然存在 Parallel 是最佳选择的用例。随着 ZGC(自 JDK 15 以来的生产就绪)的引入,还有第三种高性能替代方案可以加入等式。
20220318
为什么MySQL主键查询这么快?_MySQL_蝉沐风_InfoQ写作平台文章首发于公众号「蝉沐风」,认真写好每一篇技术文章,欢迎大家关注交流这是图解MySQL的第3篇文章,这篇文章会让大家清楚地明白:什么是InnoDB行格式?InnoDB页是什么?InnoDB页和Innohttps://xie.infoq.cn/article/a9676d1d4735bcf402b27106b一条SQL更新语句是如何执行的?_MySQL_蝉沐风_InfoQ写作平台文章首发于公众号「蝉沐风」,认真写好每一篇文章,欢迎大家关注交流这是图解MySQL的第2篇文章,这篇文章会通过一条SQL更新语句的执行流程让大家清楚地明白:什么是InnoDB页?缓存页又是什么?为什么https://xie.infoq.cn/article/d35e15ca1247e6d5dbd7fe75e
20220315
"build": "rimraf dist/ && babel ./ --out-dir dist/ --ignore ./node_modules,./.babelrc,./package.json,./npm-debug.log --copy-files", "start": "npm run build && node dist/index.js"
20220314
20220310
20220304
JSON 类型比较适合存储一些修改较少、相对静态的数据
20220303
SpringBoot中的spring-boot-starter-actuator依赖已经集成了对Micrometer的支持,其中的metrics端点的很多功能就是通过Micrometer实现的,prometheus端点默认也是开启支持的,实际上actuator依赖的spring-boot-actuator-autoconfigure中集成了对很多框架的开箱即用的API。
其中prometheus包中集成了对Prometheus的支持,使得使用了actuator可以轻易地让项目暴露出prometheus端点,作为Prometheus收集数据的客户端,Prometheus(服务端软件)可以通过此端点收集应用中Micrometer的度量数据。
20220302
微软api 规范
Restful 复杂查询
一般来说,对于查询类的API,主要就是要完成四种操作:排序,过滤,搜索,分页。下面是一些相关的规范。参考于两个我觉得写的最好的Restful API的规范文档,Microsoft REST API Guidelines,Paypal API Design Guidelines。
-
排序。对于结果集的排序,使用
sort
关键字,以及{field_name}|{asc|desc},{field_name}|{asc|desc}
的相关语法。比如,某API需要返回公司的列表,并按照某些字段排序,如:GET /admin/companies?sort=rank|asc
或是GET /admin/companies?sort=rank|asc,zip_code|desc
-
过滤。对于结果集的过滤,使用
filter
关键字,以及{field_name} op{value}
的语法。比如:GET /companies?category=banking&location=china
。但是,有些时候,我们需要更为灵活的表达式,我们就需要在URL上构造我们的表达式。这里需要定义六个比较操作:=
,<
,>
,<=
,>=
,以及三个逻辑操作:and
,or
,not
。(表达式中的一些特殊字符需要做一定的转义,比如:>=
转成ge
)于是,我们就会有如下的查询表达式:GET /products?$filter=name eq 'Milk' and price lt 2.55
查找所有的价柗小于2.55的牛奶。
我的想法 priceLT=2.55 && priceGT=2 这样能同时统一处理前端传参数和后台sql判断的问题
RL,LL,AL,IN,NO,GT,GT,LT,LE
-
搜索。对于相关的搜索,使用
search
关键字,以及关键词。如:GET /books/search?description=algorithm
或是直接就是全文搜索GET /books/search?key=algorithm
。 -
分页。对于结果集进行分页处理,分页必需是一个默认行为,这样不会产生大量的返回数据。
- 使用
page
和per_page
代表页码和每页数据量,比如:GET /books?page=3&per_page=20
。 - 可选。上面提到的
page
方式为使用相对位置来获取数据,可能会存在两个问题:性能(大数据量)与数据偏差(高频更新)。此时可以使用绝对位置来获取数据:事先记录下当前已获取数据里最后一条数据的ID
、时间
等信息,以此获取 “该ID之前的数据” 或 “该时刻之前的数据”。示例:GET /news?max_id=23454345&per_page=20
或GET /news?published_before=2011-01-01T00:00:00Z&per_page=20
。
- 使用
“一把梭:REST API 全用 POST” | 酷 壳 - CoolShellhttps://coolshell.cn/articles/22173.html
链路视图的核心参数可以集成 Slf4j 组件中,这里可以参考org.slf4j.MDC
语法,MDC 提供日志前后的参数传递映射能力,内部包装 Map 容器管理参数;在 Logback 组件中,StaticMDCBinder
提供该能力的绑定,这样日志打印也可以携带链路视图的标识,做到该能力的完整集成。
20220301
mysql8 目录权限的问题
/etc/apparmor.d/usr.sbin.mysqld
systemctl restart apparmor (app armor app盔甲)
20220225
过度设计有可能摧毁你的初创公司,它可能:
-
增加不必要的复杂性。
-
增加开发和维护成本。
-
降低你的迭代速度。
-
使你无法适应市场。
20220224
20220223
Vue 非常实用的自定义指令-51CTO.COMhttps://developer.51cto.com/article/702249.html
20220222
20220218
算法的时间复杂度
20220211
20211231
https://github.com/H5-Dooring/dooringxhttps://github.com/H5-Dooring/dooringx
https://github.com/zh-lx/pinyin-prohttps://github.com/zh-lx/pinyin-pro
20211229
我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题:如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。
那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务呢?
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。
20211224
20211021
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)