<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[Se7en0728的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/Se7en0728</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; Se7en0728]]></copyright><item><title><![CDATA[Mysql 中乐观锁和悲观锁是怎么实现的]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/155345929</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/155345929</guid><author>Se7en0728</author><pubDate>Fri, 28 Nov 2025 11:06:34 +0800</pubDate><description><![CDATA[乐观锁不是 Mysql 中内置的锁机制，而是一种基于版本控制的逻辑。悲观锁适用于，并发冲突严重的业务场景，需要确保操作绝对成功，且可以接受其他请求被阻塞等待的成本。事务开始读取数据时，要将数据加上一个排他锁，阻止其他事务修改。乐观锁适用于并发冲突没那么严重的业务场景，例如用户数据更新，性能较好但需要处理冲突。乐观锁，是比较乐观的，认为冲突不太经常发生，所以核心是先操作，提交时检查冲突。悲观锁，是比较悲观的，认为冲突很有可能发生，所以核心是先加锁，再操作。......（待续未完。诚恳欢迎大家提出意见。]]></description><category></category></item><item><title><![CDATA[计算机网络 - 在浏览器中输入 URL 地址到显示主页的过程？]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/147314370</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/147314370</guid><author>Se7en0728</author><pubDate>Fri, 18 Apr 2025 15:02:57 +0800</pubDate><description><![CDATA[第一步，浏览器通过 DNS 来解析 URL，得到相应的 ip 地址（到哪里找) 和 方法（做什么）第三步，建立好连接后，浏览器会组装 HTTP 请求报文，通过刚建立的 TCP 连接发送给服务器。第五步，浏览器在收到响应报文后就解析 HTML，CSS 和 Javascript，渲染页面。第四步，服务器在收到请求报文后，进行相应处理，之后返回 HTTP 响应。第六步，接着，完成数据传输后，通过四次连接断开  TCP 连接。第二步，浏览器于服务器建立 TCP 三次握手连接。诚恳欢迎大家提出意见。]]></description><category></category></item><item><title><![CDATA[计算机网络 - UDP协议]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/147312022</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/147312022</guid><author>Se7en0728</author><pubDate>Thu, 17 Apr 2025 21:30:08 +0800</pubDate><description><![CDATA[所以，依照 TCP 的可靠性保证，使用 UDP 的时候，可以为每个数据包附加序号，接收方返回 ACK，发送后启动计时器，利用滑动窗口机制控制发送速率，同时动态调整发送速率。TCP 的可靠性由多方面保证，比如序列号解决乱序问题，ACK 确保接收方成功接收，超时重传解决丢包问题，流量控制防止发送方压垮接收方，拥塞控制避免网络堵塞。，但是正因为 UDP 协议的控制字段较少，在数据传输过程中延迟小、数据传输效率高，适合对可靠性要求不高的服务。UDP是用户数据报协议，它是一种无连接的传输层协议，它没有可靠性保证。]]></description><category></category></item><item><title><![CDATA[计算机网络 - TCP协议]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/147256565</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/147256565</guid><author>Se7en0728</author><pubDate>Wed, 16 Apr 2025 15:25:59 +0800</pubDate><description><![CDATA[首先 TCP 是处在传输层的面向流的协议的协议，它本身不会按照应用开发者的期望，保持每次发送时都带有一个数据的边界，这可能导致接收端一次收到了多个应用层报文，需要应用开发者自己分开，也就是需要自己去实现“流”到“数据报”的功能。而如果发送方发送的太慢，数据就会有一定的延迟。而拥塞控制不同于流量控制，它主要强调的是网络的拥塞，导致发送方发的数据包被堵在了半路，而接收方迟迟没收到数据包并返回接收到的最后一个包的确认报文，会让发送方误以为这个包丢了并重新发送，这不仅会浪费信道资源，还会使原来拥塞的网络雪上加霜。]]></description><category></category></item><item><title><![CDATA[计算机网络 - 四次挥手相关问题]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/147233626</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/147233626</guid><author>Se7en0728</author><pubDate>Tue, 15 Apr 2025 19:18:59 +0800</pubDate><description><![CDATA[第二个目的的话，先等第一个 MSL 确保主动关闭端发出的最后一个 ACK 值从网络消失，再等第二个 MSL 是为了防止对端在收到这个 ACK 前的一刹那时间可能触发重传机制，等这个重传的 FIN 报文消失的时间也需要 1MSL，总共就是 2MSL。第三次挥手，服务端将剩余数据发送完成后，会发送一份携带 FIN 的报文给客户端，且指定一个序列号，告诉客户端自己也不再发送数据了，服务端处于 LAST-ACK 阶段。主要就是在一二次握手后，服务端可能还有遗留的数据需要处理，也就是需要确保数据的完整性。]]></description><category></category></item><item><title><![CDATA[计算机网络 - 三次握手相关问题]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/147161495</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/147161495</guid><author>Se7en0728</author><pubDate>Mon, 14 Apr 2025 21:11:36 +0800</pubDate><description><![CDATA[但假如由于网络原因，客户端发送的第三次握手包丢失了，但接着发送的数据包正常被服务端接收，由于这个数据包也带有 ACK 的值，服务端就会把这个数据包当作第三次握手包，先建立连接再正常读取数据。这个问题 RFC 文档中提到过，第三次握手时，客户端向服务端返回的报文中可以携带数据，即使此时服务端是 SYN_REVEIVED 状态，但由于数据报中也带有 ACK 的值，服务端接受之后会先确定这个 ACK，然后建立连接，进入 ESTABLISHED 状态，之后就能正常接受这个数据包了。]]></description><category></category></item><item><title><![CDATA[JVM - 垃圾回收器常见问题]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/146539784</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/146539784</guid><author>Se7en0728</author><pubDate>Fri, 28 Mar 2025 15:55:33 +0800</pubDate><description><![CDATA[G1 垃圾回收器，将堆内存分为许多个 Region 块，最多有 2048个，每块 Region 块的大小必须是 2 的倍数，例如 1MB，2MB。这个过程，就会不断产生新的对象，许多对象也会失去引用。接着进行到重新标记阶段，因为第二阶段又产生了许多新对象，所以这个阶段要继续让其他工作线程停下来，然后重新标记下第二阶段新创建的对象，还有一些已有对象可能失去引用变成垃圾的情况。如果垃圾回收的时候，其他应用线程也在进行，可能回导致数据不一致，比如刚把一个垃圾回收掉了，而后面突然又引用到了，引用内存回收错误。]]></description><category></category></item><item><title><![CDATA[JVM - 垃圾回收基本问题]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/146486718</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/146486718</guid><author>Se7en0728</author><pubDate>Thu, 27 Mar 2025 20:52:07 +0800</pubDate><description><![CDATA[比方说 JVM 内存结构中的虚拟机栈，虚拟机栈中有栈帧，栈帧里面存储着有指向堆的对象引用，那么位于虚拟机栈顶就可以称作是 “活跃” 的栈帧，因为此刻它正在被线程调用。标记复制算法，简单来说，就是将新生代空间分为两部分，把新创建的对象放在其中一块，等要进行垃圾回收的时候，则先将存活对象移动到另一块空间当中，然后将垃圾对象回收。如果没有垃圾回收机制的话，则存放对象的内存空间很快就会被塞满，所以为了保证系统能正常地执行，就必须要有垃圾回收机制，回收掉没有被使用的对象，也就是垃圾对象。诚恳欢迎大家提出意见Orz。]]></description><category></category></item><item><title><![CDATA[JVM - 类加载相关]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/146540728</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/146540728</guid><author>Se7en0728</author><pubDate>Thu, 27 Mar 2025 11:12:04 +0800</pubDate><description><![CDATA[应用程序加载器（Application ClassLoader）：这个类加载器就负责去加载 “ClassPath” 环境变量所指定的路径中的类，简单来说，就是加载你自己写的 Java 代码中的类。打破双亲委派思路就是在加载类时，不按照依次往上匹配类加载器的方式加载。当应用程序类加载器需要加载一个类时，会先委派给其父类加载器，即扩展类加载器，接着扩展类加载器又委派给启动类加载器。接着启动类加载器找不到这个类，则会交给扩展类加载器，如果扩展类加载器也找不到，又会交给应用程序类加载器执行。]]></description><category></category></item><item><title><![CDATA[JVM - 年轻代和老年代]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/146513022</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/146513022</guid><author>Se7en0728</author><pubDate>Wed, 26 Mar 2025 09:24:28 +0800</pubDate><description><![CDATA[每一次 Minor GC 之前，会检查老年代老年代可用空间是否大于年轻代所有对象大小，因为可能 GC 之后，所有的年轻代对象都存活下来了。大致规则就是，假设当前放对象的 Survivor 区中，有一批对象的总大小大于了这块区域的 50%，则所有年龄大于等于这批对象年龄的对象，都可以直接进入老年代。Young GC之前，如果加入堆内存的对象足够大，则直接进入老年代，可通过 JVM 参数 “-XX:PretenureSizeThreshold” 来设置这个值，单位是字节。小于的话，则会进行 Full GC。]]></description><category></category></item><item><title><![CDATA[Mysql - 锁常见问题]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/146327357</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/146327357</guid><author>Se7en0728</author><pubDate>Mon, 17 Mar 2025 22:46:14 +0800</pubDate><description><![CDATA[行锁可以做到只锁定需要操作的记录行或间隙，具体可以分为记录锁，间隙锁和 临建锁，也就是记录锁加间隙锁的组合，它锁的是一个范围。虽然用户 A 和用户 B 在 T1，T2时刻都看到还有一件商品，但最终只有用户 A 在 T3 时刻能够获得最后一件商品，此时 version 自赠为 1，那么用户 B 在 T4 时刻将无法看到这条记录，也就无法购买成功。对于行锁来说，数据行是可以加上锁的实体，但其实数据行之间的间隙也是可以加上锁的实体，对于的锁就是间隙锁。按照锁的粒度，可以分为全局锁，表级锁和行锁。]]></description><category></category></item><item><title><![CDATA[Mysql - 日志相关问题 ]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/146217195</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/146217195</guid><author>Se7en0728</author><pubDate>Mon, 17 Mar 2025 22:16:57 +0800</pubDate><description><![CDATA[可以的，由于每个事务执行时，在提交事务前都会将对数据的修改记录到 undo log 中，现在假设 Mysql 正在执行某个事务时突然宕机，如果此时事务还没有提交，那么恢复时系统会通过 undo log 依次对数据进行相反操作，比如已经 insert 了一条记录，那么就 delete 这条记录等等，对这个未完成的事务进行回滚，确保事务的原子性；redo log 是 InnoDB 独有的，记录的是某个数据页做了什么修改，每执行一个事务就会产生相应的 redo log。其中还用到 WAL 技术。]]></description><category></category></item><item><title><![CDATA[Mysql - 事务基础]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/146170290</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/146170290</guid><author>Se7en0728</author><pubDate>Tue, 11 Mar 2025 22:59:31 +0800</pubDate><description><![CDATA[在  RR（可重复读）隔离级别下，当一个事务开始时，会生成唯一的事务 ID，当事务需要更新数据时，Mysql 并不会直接修改原始数据，而是将原始数据先复制一份，并将其版本号 +1，再将更新的内容写进 undo log。即开启事时，看到的数据是静态的，能很好解决不可重复的问题，不过会遇到幻读的问题。这个级别下的事务，做的数据操作没提交就能被其他事务看到，具有很好的并发性，不过容易发生脏读，不可重复读等问题。，每个事务都是相互隔离，不能相互影响，在事务提交前，事务的操作是对外不可见的。]]></description><category></category></item><item><title><![CDATA[Mysql - InnoDB 和其他存储引擎的区别]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/146146410</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/146146410</guid><author>Se7en0728</author><pubDate>Mon, 10 Mar 2025 11:52:25 +0800</pubDate><description><![CDATA[而内存表的索引都是一样的，根据数据位置走一次查找即可。而且 Memory 的数据是存储在内存当中的，数据不支持持久化，但会有速度快的优势。Memory 引擎比较适用于需要内存临时表的场景，内存临时表数据量小，不容易被其他线程访问，没有并发性问题。同时，临时表重启后数据需要删除，这也符合内存表的特性。而 InnoDB 表有行锁，能很好的处理并发，而且 InnoDB 的数据会写入磁盘当中，数据不容易丢失。其他情况都建议使用 InnoDB，因为 InnoDB 可以较好的处理并发量高的事务，同时能持久化数据。]]></description><category></category></item><item><title><![CDATA[Mysql - 自增主键的使用细节]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/146146360</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/146146360</guid><author>Se7en0728</author><pubDate>Mon, 10 Mar 2025 11:19:14 +0800</pubDate><description><![CDATA[使用身份证号做主键的每个非主键索引叶子节点的大小约为 20 字节，而如果使用自增主键，则只要 4 个字节，如果是长整型也就 8 个字节。INT 类型的自增主键的最大数是 2^32 - 1(4294967295)，如果达到这个值，后面再插入的话，得到的值将会保持不变。可以看到，第一条插入语句还是成功的，第二条插入语句就失败了，证明了 INT 类型的自增主键超过了最大值后申请的 id 还是一样的。2. 自增主键的话，如果用 INT，会有 int 最大数限制，如果超过 int 最大数，你觉得应该怎么办？]]></description><category></category></item><item><title><![CDATA[Mysql - 索引分类相关]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/146063468</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/146063468</guid><author>Se7en0728</author><pubDate>Thu, 06 Mar 2025 23:26:18 +0800</pubDate><description><![CDATA[当需要更新一个数据页中，而数据页又没在内存当中，就会将更新操作记录在 change buffer 中，当下次查询该数据页时，将数据页读入内存，就会执行 change buffer 中与这个页有关的操作。对于一个整型字段，一个数据页是可以存放许多 key的，所以连续相同的值充满整张数据页的概率是很低的，即代表普通索引可以在一个数据页中完成查询，所以二者查询性能并没有多少差距。除主键索引外，其他索引就是非主键索引，也可以视作辅助索引。这里主要是主键索引，非主键索引，唯一索引，普通索引，联合索引等等。]]></description><category></category></item><item><title><![CDATA[Mysql - 索引优化相关]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/146028429</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/146028429</guid><author>Se7en0728</author><pubDate>Thu, 06 Mar 2025 10:04:20 +0800</pubDate><description><![CDATA[亦或者 sql 语句本身没有什么问题，而是 Mysql 统计基数出现差错，使用错了索引，我们可以通过 explain 来查看语句的执行计划，再通过 FORCE INDEX 强制使用索引来进行对比，从而排查速度慢的原因。一般情况下，给一些频繁需要使用的字段，和一些区别度高的字段加索引是比较合适，其次还要考虑字段的长度，过长会占用空间，过短会导致区分度减低，比如身份证号只取前 6 位情况。比如电商支付下的订单表。当然，还有第二种方法，我们可以考虑修改语句，引导 Mysql 使用我们期望的索引，比如，]]></description><category></category></item><item><title><![CDATA[Mysql - 索引底层实现]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/145999417</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/145999417</guid><author>Se7en0728</author><pubDate>Tue, 04 Mar 2025 15:27:36 +0800</pubDate><description><![CDATA[同时，B+ 树非叶子节点只存储键值，叶子节点才存储具体数据，这样会使树的整体大小缩小，方便内存可以一次性加载更多的节点。B 树也是一种多叉树，不过 B 树的节点会存储具体的数据，所以相同大小的磁盘页，B 树可以容纳的键值更少。B 树相对于其它数据结构，磁盘访问性能还是较优的，大多数用在文件系统中，比如在 Windows NTPS 文件系统中，每个目录对应着一个 B 树节点，可以快速地对文件进行查找和访问，提高文件系统性能。除了主键索引，还有非主键索引，非主键索引中只有索引值和对应的主键索引，并没有行记录。]]></description><category></category></item><item><title><![CDATA[Java集合 - ArrayList 和 LinkedList]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/145971591</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/145971591</guid><author>Se7en0728</author><pubDate>Sun, 02 Mar 2025 22:47:18 +0800</pubDate><description><![CDATA[ArrayList 的默认容量是 10，当需要扩容时，会先申请一个容量为旧数组 1.5 倍的新数组，然后将旧数组复制到新数组当中去。但在执行插入和删除节点时，会涉及数组的复制和移动，所以复杂度为 O(n)ArrayList 的话，会先以 O(1) 的时间定位到第 k 个元素，然后将被这个数组分割的两部分复制拼接到一个新数组上，整体为 O(n)LinkedList首先会用 O(n) 的时间定位到第 k 个元素，然后花 O(1）的时间去进行 remove，总体也为 O(n)诚恳欢迎大家提出意见Orz。]]></description><category></category></item><item><title><![CDATA[Java基础 - final关键字的理解和使用时机]]></title><link>https://blog.youkuaiyun.com/Se7en0728/article/details/145955664</link><guid>https://blog.youkuaiyun.com/Se7en0728/article/details/145955664</guid><author>Se7en0728</author><pubDate>Sat, 01 Mar 2025 23:34:27 +0800</pubDate><description><![CDATA[被 final 修饰过的类，不能被继承。Java 的核心类库中就有许多类被 final 修饰，比如 String 类，为了保证 String 类的不可变性，Java 设计者就通过 final 关键字来禁止这些核心类被修改。还有 final 修饰的方法，不能被子类重写，就是为了防止方法逻辑被修改，保证方法逻辑的稳定性。final 在英文中的意思是：最终的，不可更改的，其实它的作用就可以从英文本意中引导出来。final 是 Java中的一个关键字，它可以修饰类，方法，属性。诚恳欢迎大家提出意见Orz。]]></description><category></category></item></channel></rss>