目录

ThasBlog

学无止境

关于本站 置顶! 有更新!

服务端: solo: 基于Java语言开发的博客系统, 可动态在线编辑, 可导出静态站点. 动态站点: https://i.thas.ltd: 托管在腾讯云上, 已备案. 静态站点: https://thas.cc: 托管在github上, CDN是 https://vercel.com/(原名https://zeit.co/), 免备案.

分布式事务

角色 RM 资源管理者,通常指数据库 TM 事务协调者,协调事务 AP 应用,事务的参与者 2PC Prepare 准备事务(开启一个事务,执行SQL),通常依赖于数据库事务 Commit 提交事务,通常就是数据库事务Commit 问题: 性能问题 1.1. 2PC是同步的强一致性方案,依赖数据库事务的 Prepare,需要锁定资源,如果某个事务一直拿不到锁,会导致所有人一直阻塞,有很大的性能浪费(参考 BIO) 1.2. 网络问题,也会导致锁定时间变长 单点故障问题 TM 故障会导致所有协调者阻塞 一致性问题 3.1 Commit阶段不一致,会导致部分提交问题,需要由TM 来保证最终一致 3.2 最终一致问题: 没有回头路,已提交的事务不能回滚,必须要将所有分支事务 Commit成功,否则就要人工干预 XA TM与RM之间的开放协议* 3PC 对2PC事务的改进 CanPrepare 询问各分支事务能否取得锁,缓解了 1.1 问题 PreCommit 跟Prepare一致,加入了分支事务超时机制,缓解了 2 问题 DoCommit 同 Commit 问题:....

SQL 优化的几种方式 有更新!

高性能索引 建立三星索引: 一星:根据索引能够确定一段较小的范围,散列好的字段靠前 二星:查询结果排序与索引排序一致,联合索引从做到右有序。 三星:宽索引,查询结果尽可能在索引中找到(覆盖索引),避免回表 索引使用注意点: 不要在索引列上做运算 尽可能全值匹配 (唯一确定一条索引) 最左匹配原则 范围条件放最后 覆盖索引 不等于要慎用 Null 和 Not Null, 尽可能不要使用null, null有很歧义 like查询只能匹配做前缀 字符串要加引号 or的所有条件都必须要有索引,否则会全表扫描 使用索引排序来做排序,从左到右依次有序,中间索引单独排列是无序的 使用自增主键,顺序插入(MySQL B+树特性) 移除无用的索引 插入或修改数据都需要修改索引,无用索引会浪费插入时的性能。 分页优化 分页查询时,offset的那部分依然会被查询到,只是在返回客户端时被丢弃了 (也就是查询到了大量不必要的数据),先根据条件查询 ID(不回表),再根据ID查询其他字段(子查询)。 此种办法会多物化出一个子查询结果集。 通过手动指定 MaxId 限定查询的起始位置。 查询降级 当查询无可避....

Jvm GC 示例代码 有更新!

jvm参数: -Xms1000m -Xmx1000m -XX:NewRatio=9 -XX:SurvivorRatio=8 -XX:-UseParNewGC -XX:-UseConcMarkSweepGC -XX:+UseSerialGC -XX:+PrintGC -XX:+PrintGCDetails -XX:-UseTLAB java代码: public class Main { static Object[] bs = new Object[500]; public static void main(String[] args) throws Exception { //预留时间连接console Thread.sleep(20000); // 消除程序初始化的影响 System.gc(); for (int i = 0; i < bs.length; i++) { // 分配1mb //建立强引用 bs[i] =new byte[1024*1024]; Thread.sleep(200); } System.gc(); Thread.sleep(10000); } } ....

Deepin 处理软件包 dde-api (--configure)时出错

root@xcc-deepin:/var/lib# dpkg --configure dde-api 正在设置 dde-api (5.4.9-1) ... mkdir: 无法创建目录 “/var/lib/deepin-sound-player”: 权限不够 dpkg: 处理软件包 dde-api (--configure)时出错: 已安装 dde-api 软件包 post-installation 脚本 子进程返回错误状态 1 在处理时有错误发生: dde-api 检查 post-installation 脚本 vi /var/lib/dpkg/info/dde-api.postinst 添加-x调试 重新执行 dpkg --configure dde-api 发现问题 以 deepin-sound-player 的身份创建目录,而 /var/lib 权限是 755,所有权限不够, 修改为 777, 保证 /var/lib 对其他用户可写 done

MySQL 范式

常见的三范式: 数据表的所有字段必须是原子的, 不可拆分的 数据表的每条记录必须是唯一的, 要有一个主键标识, 不能由多个字段共同确定一条记录的唯一性 数据表关联其他数据表时, 不能存在其他数据表主键字段以外的其他字段 反范式: 反第一范式: 针对已有记录做创建缓存表和汇总表 反第二范式: 计数器表, 并发对同一条数据进行修改, 冲突大, 效率低, 拆成多条记录减少并发修改(类似ConcurrentHashMap记录) 反第三范式: 冗余字段, 减少连接查询. 分库分表中用得比较多, 连接查询开销大

MySQL 事务

事务特性: 原子性 一致性 隔离性 持久性 事务并发问题: 脏读 读到了未提交的事务 脏写 未提交的事务覆盖了已提交的事务 幻读 读到了别人新插入的数据 不可重复读 多次读取数据不一样, 被已提交的事务修改了值 写入偏差 已提交的事务覆盖了已提交的事务, 造成了不一致的问题, 通常是业务上进行保证 事务隔离级别: 读未提交 基本不用, 脏读,脏写,幻读,不可重复读均存在 读已提交 用的比较多, 不能避免幻读, 不可重复读 可重复读 存在幻读问题, MySQL使用间隙锁解决了幻读问题 串行化 基本不用, 无高性能

Ubuntu/Deepin 英伟达显卡驱动安装 有更新!

手动安装驱动 屏蔽三方驱动 nouveau sudo vim /etc/modprobe.d/blacklist-gpu.conf # ban nouveau blacklist nouveau blacklist lbm-nouveau options nouveau modeset=0 alias nouveau off alias lbm-nouveau off 更新内核并重启 sudo update-initramfs -u sudo reboot 注意 deepin 有多个内核 关闭图形界面 sudo systemctl stop lightdm 安装驱动 chmod +x NVIDIA-Linux-x86_64-465.31.run sudo ./NVIDIA-Linux-x86_64-465.31.run --no-opengl-files --no-x-check --no-nouveau-check 参数不加也没事 卸载驱动 sudo nvidia-uninstall sudo nvidia-installer --uninstall sudo apt-get ....

Ubuntu Kylin 安装 有更新!

下载安装 显卡驱动 ./amdgpu-pro-install -y --opencl=pal,legacy --px glxinfo | grep rendering 显示yes说明正常 sudo radeontop -c 查看显卡使用情况 设置livepatch https://auth.livepatch.canonical.com/?user_type=ubuntu-user keymanager https://www.keymanager.org/ crossover https://www.crossoverchina.com/chanpin.html 启动脚本 sudo ln -s /usr/local/jetbrains/idea-IU-203.7148.57/bin/idea.sh /usr/bin/idea docker https://hub.docker.com/editions/community/docker-ce-server-ubuntu oh-my-zsh https://ohmyz.sh/#install https://....

MySQL 体系架构 有更新!

MySQL架构分为3部分, 连接层, Server层, 引擎层. 连接层负责服务端与客户端的连接, 会话和权限验证. Server层包括SQL接口, 解析器, 优化器和查询器. 引擎层则是数据存储的具体的实现.

记一次线上 JAVA 程序 OOM 事件 有更新!

依赖三方包: <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency> <!-- 阿里云SLS提供的SDK --> <dependency> <groupId>com.aliyun.openservices</groupId> <artifactId>aliyun-log</artifactId> <version>0.6.56</version> </dependency> 代码: public class DefaultServiceClient2 extends DefaultServiceClient { // 问题的主要原因出在这个 DefaultServiceCl....

Java 方法调用的底层实现 有更新!

Java 方法调用通过字节码指令 invokestatic, invokespecial, invokevirtual, invokeinterface, invokedynamic 来实现方法调用. 非虚方法 非虚方法指能够在运行时直接确定其调用地址的方法, 这些方法在类加载完成之后, 其内存地址都是不会再变化的, 可以直接访问调用. invokestatic: 静态方法调用 invokespecial: 私有实例方法调用, 构造方法或 super 方法, 被 final 修饰的实例方法 虚方法 由于多态的特性, 方法可以被不同的子类覆写, 所以对于同一个方法, 它们的实现不同, 对应的方法的目标地址也是不一样的, 通过查方法表来实现动态调用. invokevirtual: 可被覆写的实例方法, 大部分调用方法都是这种方式. Java 对象的方法表存放在类中(与 C++不相同), 从对象实际类型开始递归向上查找类型的方法表, 第一次执行过后, 以方法位置作为索引编号建立缓存 invokeinterface: 类似invokevirtual, 但比较慢, 因为接口中方法的位置编号是无法....

Jdk 自带工具

jps, jstat, jinfo, jstack, jmap, jconsole, visualVm jps java 进程状况查看 jps -q 只显示进程号 jps -m 查看启动类 jps -v 查看详细启动参数 jstat jstat -class 显示类加载情况 jstat -gc [统计间隔] [统计次数] 查看 gc情况 S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT CGC CGCT GCT 44480.0 44480.0 0.0 8352.5 355840.0 352724.5 889256.0 296943.0 522908.0 503674.2 67120.0 59766.6 6169 27.923 6 6.963 50 6.401 41.287 C: capacity U: used S0: suvivor0 S1: suvivor1 E: eden O: old M: metaspace CCS: 压缩类 C: count T: time 时间 YG: 年轻代GC FG: fullg....

Java JMM 有更新!

JVM 使用线程工作内存和主内存这两个概念来抽象物理内存结构, 从而屏蔽掉各平台各操作系统的内存结构差异。 JMM 为保障这套抽象内存结构的并发安全, 提供了协议和工具的支持。

Java AQS 有更新!

AQS AbstractQueuedSynchronizer, 队列同步器, 支持队列等待。 继承自 AbstractOwnableSynchronizer, 不带队列的同步器, 只能有一个线程同步, 其他线程忽略。 AQS 使用 state 和 一个 FIFO 队列来进行线程同步。 state 表示申请资源的状态, 默认 0, 若已被占用则小于 0. AQS 不关注申请和释放资源的方式, 只提供了操作 state 的方法。 在并发申请资源过程, AQS 维护各个线程获取资源的原则, 如不满足获取资源的条件, 则先将它们放入等待队列, 等待资源可以被申请了, 再唤醒等待队列中的线程。 申请和释放资源的方法需要锁自己实现: 1// 尝试申请资源 2boolean tryAcquire(int arg) 3// 尝试释放资源 4boolean tryRelease(int arg) 5// 资源是否被独占 6boolean isHeldExclusively() 7// 尝试以共享模式申请资源 8int tryAcquireShared(int arg) 9// 尝试以共....

JAVA 对象头 有更新!

对象头结构 偏向锁与 hash 不能共存, 一旦计算过 hash, 对象就不可偏向。 对象头中的 bl:1 代表是否可偏向, 若不可偏向, 则前 56 位可以用来表示 hash 值, 若可偏向, 则前 56 位必不表示 hash 值, 可以用来表示偏向的线程 ID Object 没有属性, 所以除了对象头就没有其他内容了, 根据 8 字节对齐, 自动填充了 4 字节 Object[]数组会额外使用 4 字节保存长度, 所以数组的最大长度为整形; 后面则是顺序存储的全部元素的指针, 由于开启了指针压缩, 每个都是 4 个字节。 指针压缩 32 位 CPU 的最大寻址空间为 2^32, 如果这些寻址空间指向 bit 位, 那么最大支持的内存为 512M; 但是 CPU 存储数据的时候都是以 8bit 为一组, 也就是 1byte; 把寻址空间指向 byte 组, 就可以让最大支持内存增加到 4G. JVM 指针压缩原理相同。 64 位 JVM 最大寻址空间是 2^64, 寻址空间指向 byte 组, 则最大可支持 2^34G 内存; 但是存储 64 位指针会让内存占用提高。 由于 J....

JAVA 内存区域 有更新!

Java 内存区域包括虚拟机栈, 本地方法栈, 程序计数器, 堆, 方法区。

Java8 ConcurrentHashMap 有更新!

ConcurrentHashMap 是 HashMap 的线程安全版本, 使用了 CAS, volatile 和 synchronize 技术。 初始化时使用 volatile 修饰的 sizeCtl 作为互斥条件, 如果有其他线程正在操作则 Thread.yeild(). 在插入元素时, 如果元素不存在, 则使用 CAS, 在插入新元素时, 如果元素不存在才能插入成功, 否则失败重试, 如果是 MOVED 状态, 则先辅助扩容, 完成后再尝试插入。 如果元素存在, 需要进行修改或者 Hash 冲突, 则加 synchronize 锁进行处理(因为情况比较复杂, 可能是链表, 可能还需要树化), synchronize 修饰 bin 上的第一个元素 元素数量修改时, 并发高的情况容易 CAS 失败, 引入 counterCells 数组减小 CAS 失败的概率 数组扩容时, 分段迁移, 每段最少 16, 迁移前 CAS 设置 transferIndex, 设置成功则得到该小段的迁移的权利。 迁移时, 如果该 bin 上有值, 则 synchronize 锁住, 如果无值, 则 CAS....

Java8 HashMap 有更新!

HashMap Map 意思是映射, 从 key 映射到 value. HashMap 就是基于 hash 的 key 来实现映射关系。 数组是在连续的固定大小的内存空间上顺序且紧凑地存储元素的集合。 数组支持随机读写, 其本质原因就是紧凑存储。 通过数组头部位置 + 索引就可以直接获得指定元素的地址, 对该地址直接进行读写。 但紧凑存储同时带来另一弊端, 为了保证数组元素紧凑, 每次在数组中间增删元素时都需要挪动数组元素以保证数组中间没有空缺。 数组索引 = 元素在数组中的位置, 数组索引是顺序的且永远不会重复。 Hash 表继承了数组的优点, 支持随机读写, 又不需要(频繁)挪动元素。 牺牲了少量额外内存空间和散列计算开销。 Hash 索引 = 散列函数(元素), Hash 索引不是顺序的, 只与元素本身相关, 但是是可能重复的。 当 Hash 索引重复时, 一个索引会对应多个元素, 这就是 Hash 碰撞, 这时 Hash 表随机读写的优势就会降低。 适当的增加 Hash 表分配的内存空间可以减少 Hash 碰撞几率, 所以 Hash 表通常会有额外的未利用内存空间。 链地址法(....

红黑树 有更新!

红黑树是特殊的二叉平衡搜索树。 特点: 所有节点均为黑色或红色节点。 根节点一定为黑色节点。 叶子节点均使用 NIL 黑色节点填充。 不能出现连续的红色节点。 根节点到叶子节点的所有路径具有相同数量的黑色节点。 红黑树保证平衡的重要手段是左旋/右旋以及变色。 模拟器:https://www.cs.usfca.edu/~galles/visualization/RedBlack.html 二叉搜索树左子节点 < 根节点 < 右子节点, 无论左旋还是右旋始终满足这个大小关系。 左旋/右旋这两种手段适用于全部的二叉搜索树, 而不仅仅是平衡树。 红黑树保持平衡的方式: 大前提: 新插入的节点永远是红色. (如果是黑色, 那就没有红色了, 全靠黑色节点来保障平衡, 那就退化成严格平衡二叉树了) 1 新插入节点的父节点是黑色节点, 红黑树依然保持平衡, 无需操作。 2 新插入节点的父节点是红色节点, 叔叔节点为黑色节点或 NIL(直接忽略叔叔节点或者将其看成一个 NIL 整体): 分为 LL/RR 和 LR/RL 两大类型。 核心思想一样, 围绕新插入节点 + 父节点 + 祖父节....