<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[small_engineer的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/small_engineer</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; small_engineer]]></copyright><item><title><![CDATA[LRUCache简单实现]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/125111943</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/125111943</guid><author>small_engineer</author><pubDate>Fri, 03 Jun 2022 13:24:06 +0800</pubDate><description><![CDATA[来源于LeetCode. 146. LRU 缓存

题目要求实现一个LRUCache，我们使用get时，需要额外把该节点移动到开头；我们使用put时，如果存在该节点，我们需要把该节点删除，并且插入到开头；不存在则插入到开头，此时需要判断长度是否大于给定的capacity。并且实现这两种操作时，时间复杂度都必须为O(1);get我们使用HashMap便可以达到我们的时间复杂度，但是HashMap不是有序的，但它的子类LinkedHashMap是有序的，所以我们使用LinkedHashMap便可以达到本题的效果]]></description><category></category></item><item><title><![CDATA[ThreadLocal底层原理详解]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124813818</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124813818</guid><author>small_engineer</author><pubDate>Tue, 17 May 2022 11:20:37 +0800</pubDate><description><![CDATA[ThreadLocal底层原理详解引言1. 什么是ThreadLocal？2. ThreadLocal的源码分析为什么Map的key要设置成弱引用呢？？value怎么释放呢？
引言
由于在项目中使用到了ThreadLocal，所以特地花一篇文章的时间来讲讲ThreadLocal的底层实现
1. 什么是ThreadLocal？
简单来说就是，ThreadLocal是依附在Thread上的局部变量，可以实现线程间的隔离，线程内部的资源共享，ThreadLocal是线程私有的；
2. ThreadLocal的源码]]></description><category></category></item><item><title><![CDATA[RDB和AOF持久化底层原理详解]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124744987</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124744987</guid><author>small_engineer</author><pubDate>Sat, 14 May 2022 10:32:43 +0800</pubDate><description><![CDATA[RDB和AOF持久化底层原理详解1. 导言2. RDB持久化2.1 RDB文件的创建和载入2.2 save命令和bgsave命令执行时服务器状态2.3 自动间隔保存2.4 RDB文件结构3. AOF持久化
1. 导言
由于我们的	Redis是一款内存性数据库，所有数据都保存在内存中。一旦断电，那么数据将会丢失，所以为了解决这个问题，Redis使用两种持久化方式进行保存，将这些内存中的数据保存到磁盘上。
2. RDB持久化
RDB持久化可以手动执行，也可以根据配置文件进行定期执行，该功能可以将数据库某个时间点]]></description><category></category></item><item><title><![CDATA[Redis数据库底层实现和过期键详解]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124723475</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124723475</guid><author>small_engineer</author><pubDate>Thu, 12 May 2022 11:32:14 +0800</pubDate><description><![CDATA[Redis数据库底层实现和过期键详解1. 服务器中的数据库底层表示2. select切换数据库原理3. 数据库键空间4. 过期时间设置和过期键删除策略4.1 过期时间设置4.2 保存过期时间4.3 过期键的判定4.4 过期键的删除策略
1. 服务器中的数据库底层表示
在src/server.h中
图1.1
图1.1中，每一个redisDb表示一个数据库，这结构里面包含了所有数据库

图1.2
图1.2中，dbnum为服务器数据库的数量，默认为16个数据库

图1.3
图1.3中表示了一个Redis的总体结构]]></description><category></category></item><item><title><![CDATA[Redis五种基本数据类型底层详解(原理篇)]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124623298</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124623298</guid><author>small_engineer</author><pubDate>Sat, 07 May 2022 13:07:14 +0800</pubDate><description><![CDATA[Redis五种基本数据类型底层详解详细介绍Redis用到的数据结构简单动态字符串SDS和C字符串的区别总结链表字典哈希表字典哈希算法解决键冲突rehash(重点)渐进式rehash跳跃表
详细介绍Redis用到的数据结构

各位，稍安勿躁，讲解五种基本数据类型前，我们先来这些数据类型用到的数据结构，防止后面懵逼,本文所用源码来源：Redis源码链接，版本使用6.2

简单动态字符串
我们都知道Redis是用C写的，但Redis中并没有直接使用C语言传统的字符串(以空字符结尾的字符数组)，而是自己构建了一种名]]></description><category></category></item><item><title><![CDATA[十大排序算法(Java版)]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124618586</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124618586</guid><author>small_engineer</author><pubDate>Fri, 06 May 2022 21:15:54 +0800</pubDate><description><![CDATA[十大排序算法总览冒泡排序流程图Java代码复杂度分析选择排序流程图Java代码复杂度分析直接插入排序流程图Java代码复杂度分析
总览


冒泡排序
流程图

Java代码
    //冒泡排序
    public void bubleSort(int arr[]){
        int len=arr.length;
        for(int i=1;i&lt;arr.length;++i){
            for(int j=0;j&lt;len-i;++j){
         ]]></description><category></category></item><item><title><![CDATA[Java并发基础概念]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124587252</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124587252</guid><author>small_engineer</author><pubDate>Thu, 05 May 2022 14:14:09 +0800</pubDate><description><![CDATA[Java并发基础概念进程与线程进程线程进程与线程的区别并行与并发并发并行同步和异步
进程与线程
进程

程序由指令和数据组成，但这些指令要运行，数据要读写，就必须将指令加载至 CPU，数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的
进程是系统分配资源的最小单元

线程

一个进程可以有多个线程
线程是cpu调度的基本单位，线程之间共享进程资源

进程与线程的区别

进程的独立的，而线程存在于进程内，是进程的一个子集
进程拥有共享的资源，供内部的线程]]></description><category></category></item><item><title><![CDATA[一文掌握MySQL中的锁]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124348372</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124348372</guid><author>small_engineer</author><pubDate>Tue, 26 Apr 2022 18:16:04 +0800</pubDate><description><![CDATA[MySQL中锁的详细介绍解决并发事务带来的问题读-读情况写-写情况读-写或写-读情况
解决并发事务带来的问题
读-读情况
并发事务同时对一条记录进行读取，本身不会对记录造成什么影响，所以允许这种情况的发生
写-写情况
并发事务同时对同一条记录进行修改的情况， 会造成脏写现象，任何一种隔离级别都不允许它的发生，所以使用加锁的方式，排队等待进行记录的修改。
这个排队的实现，是通过加锁来进行实现的。这个锁结构是在内存中实现的,在事务执行前，锁并不存在。

当一个事务对记录做改动时，需要先生成一个锁结构，然后在内存]]></description><category></category></item><item><title><![CDATA[IP协议相关技术终极详解]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124398518</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124398518</guid><author>small_engineer</author><pubDate>Tue, 26 Apr 2022 11:19:20 +0800</pubDate><description><![CDATA[IP协议相关技术DNS域名解析协议概述域名的层级关系域名的解析流程ARP地址解析协议概述
DNS域名解析协议
概述
我们在上网时，通常使用的都是域名来访问网站，因为域名更容易记住，总不可能记住一串ip地址吧。
那么网络如何将域名转换成对应的ip地址呢？这就需要我们的DNS域名解析协议了
域名的层级关系
DNS中的域名都是靠句点来进行分割的，越靠右的层级越高，因为外国人的思维都是跟中国人相反的。
根域在最顶层，它的下一层就是.com顶级域，如图所示：

根域的DNS服务器信息保存在互联网中所有DNS服务器中，]]></description><category></category></item><item><title><![CDATA[一文解决MySQL事务并发问题和事务隔离级别及MVCC原理]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124252956</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124252956</guid><author>small_engineer</author><pubDate>Thu, 21 Apr 2022 14:04:17 +0800</pubDate><description><![CDATA[事务并发产生的一致性问题
脏写
如果一个事务修改了另一个未提交事务的修改过的数据，则称发生了脏写现象。
举个例子：
假设数据库中有一个数据项为x=2；
事务A修改了x=1；此时事务A并没有提交，事务B此时也来修改数据项x=0；此时事务A,B提交
事务B修改了事务A未提交修改过的数据，所以发生了脏写的现象
脏读
如果一个事务读取了另一个事务未提交的数据，则称发生了脏读现象

不可重复读
如果一个事务A读取了x的值，然后事务B又修改了x的值并且提交，事务A再次读取x的值时，则会与第一次x的值不同，则称发生了不可]]></description><category></category></item><item><title><![CDATA[已经建立的TCP，收到SYN会发生什么？]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124314271</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124314271</guid><author>small_engineer</author><pubDate>Thu, 21 Apr 2022 13:39:19 +0800</pubDate><description><![CDATA[已经建立的TCP，收到SYN会发生什么？

该场景可以描述为：客户端与服务端建立连接后，突然客户端死机了，而服务器还处于establelisten状态，这时客户端开机后再次发送syn报文请求建立连接，那么服务端收到这个syn报文会做出什么反应呢？？

一个TCP连接是由一个四元组唯一确认的，此时源ip，目标ip，目标端口是确定的，只有源端口是不确定的。
客户端SYN报文的源端口与历史端口是不一样的
这样的话，相当于客户端重新建立起了一次新的连接
那么服务端处于establelisten状态的连接，如果服务端]]></description><category></category></item><item><title><![CDATA[SYN报文什么时候会被丢弃？]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124312088</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124312088</guid><author>small_engineer</author><pubDate>Thu, 21 Apr 2022 09:04:30 +0800</pubDate><description><![CDATA[开启tcp_tw_recycle参数，并且在NAT环境下，造成syn包丢弃
tcp最后挥手时，需要发起关闭方等待2MSL时间后才能关闭，Linux提供了两个系统参数可以快速回收time_wait状态的连接，这两个参数都是默认关闭的。

net.ipv4.tcp_tw_reuse：如果开启该选项的话，tcp在新建连接时，会自动选择time_wait状态超过1s的连接来进行复用，该选项只适用于连接方
net.ipv4_tcp_tw_recycle：如果开启该选项的话，允许处于time_wait状态的连接快速回收]]></description><category></category></item><item><title><![CDATA[如何理解TCP是面向字节流协议及粘包问题解决]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124268210</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124268210</guid><author>small_engineer</author><pubDate>Tue, 19 Apr 2022 11:15:13 +0800</pubDate><description><![CDATA[如何理解TCP是面向字节流协议

之所以说TCP是面向字节流协议，UDP是面向报文协议。主要是因为发送方的发送消息的机制不同

UDP是面向报文协议
udp在发送消息时，在传输层直接就将一个消息打包成一个完整的包，组装好udp头部，不进行切割，就转发给网络层。也就是每一个UDP报文就是一个消息。服务端在接收到udp报文时，会将它放到一个队列中，一个元素就是一个udp报文。每次读取时，读取一个元素
TCP是面向字节流协议
当tcp在传输层发送消息时，一个消息可能会被分割成多个tcp报文进行转发给网络层。我们不]]></description><category></category></item><item><title><![CDATA[TCP四次挥手详解(含常见面试题)]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124224532</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124224532</guid><author>small_engineer</author><pubDate>Tue, 19 Apr 2022 10:09:52 +0800</pubDate><description><![CDATA[TCP四次挥手过程

客户端发起fin位为1的FIN报文，此时客户端进入FIN_WAIT_1状态
服务端接受到FIN	报文后，发送ack应答报文，此时服务端进入close_wait状态
客户端接受到ack应答报文后，进入FIN_WAIT_2状态
服务端处理完数据后，向客户端发送FIN报文，此时服务端进入LAST_ACK状态
客户端接受到FIN报文后，客户端发送应答ack报文，进入TIME_WAIT阶段
服务端接受到ack报文后，断开连接，处于close状态
客户端过一段时间后，也就是2MSL后，进入clos]]></description><category></category></item><item><title><![CDATA[TCP半连接队列和全连接队列]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124190620</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124190620</guid><author>small_engineer</author><pubDate>Sat, 16 Apr 2022 09:58:51 +0800</pubDate><description><![CDATA[什么是TCP半连接队列和全连接队列？
在TCP进行三次握手时，Liunx会为其维护两个队列：

半连接队列，也叫syn队列
全连接队列，也叫accept队列

在客户端发起第一次连接时，服务端会将其加入到syn队列中，并且响应客户端syn+ack报文，等到客户端发送ack应答报文时，服务端将该连接从半连接队列中取出，并新建一个新的连接，加入到accept队列当中。等待进程调用accept请求时，将该连接取出来

不管是半连接队列还是全连接队列，都有最大长度限制，超过限制时，内核会直接丢弃，或返回 RST 包]]></description><category></category></item><item><title><![CDATA[TCP三次握手(含常见面试题)详解]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124139370</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124139370</guid><author>small_engineer</author><pubDate>Fri, 15 Apr 2022 09:34:28 +0800</pubDate><description><![CDATA[TCP 头格式


序列号：在建立连接时就由计算机随机生成，每发送一次数据，该序列号+1，用来解决网络中包乱序的问题
确认应答号：表示下一次期望收到的报文序列号，表示以前的数据报都已经收到了，用来解决网络中丢包的问题
控制位：
ACK：该位为1时，确认应答号是有效的，除了建立连接开始的syn包时，其他包该位必须为1
RST：该位为1时，表示出现异常，强制连接断开
SYN： 该位为1时，表示希望建立连接，并且初始化序列号
FIN： 该位为1时，希望正常断开连接，通信双方互相交换FIN，表示可以断开

TCP连]]></description><category></category></item><item><title><![CDATA[474. 一和零 Java(三维0/1背包)]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124182087</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124182087</guid><author>small_engineer</author><pubDate>Thu, 14 Apr 2022 21:22:51 +0800</pubDate><description><![CDATA[开始这题讲解前，需要你掌握0/1背包滚动数组版

本来看到第一眼准备用贪心的，每次取最短的字符串，不过很容易就被推翻了。便放弃了这种解法。
这题我想最难的是：想到0/1背包的贪心上面，想到了0/1背包又很难想到是个三维的0/1背包，将背包容量变成了二维。
我们将每个字符串看成是一个个物品，0和1的数量看做是它的容量.这样的话，就是一个三维的问题了，xy坐标为0和1的数量，z坐标为每个物品。依照0/1背包的滚动数组来做，本题可以转换为二维数组，因为z坐标是可以循环利用的。
dp[i][j]代表的含义为：放..]]></description><category></category></item><item><title><![CDATA[LeetCode 494.目标和(回溯+动态规划[类似0/1背包])]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124180238</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124180238</guid><author>small_engineer</author><pubDate>Thu, 14 Apr 2022 20:01:33 +0800</pubDate><description><![CDATA[最近开始写动态规划了，题解都少写好多！！！为啥呢？太tm难了，有些题看了题解还要想个几小时。终究还是菜狗！！

不说了，继续写题解，加深理解
第一种解法：回溯
这个就不用我写了吧，感觉没有技术含量。用回溯我都感觉很愧疚，因为跟暴力差不多。但是没办法，不会就老老实实写这种了
class Solution {
    int sum=0;
    public int findTargetSumWays(int[] nums, int target) {
        int length=nums.len.]]></description><category></category></item><item><title><![CDATA[MySQL日志之Undo日志]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124147425</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124147425</guid><author>small_engineer</author><pubDate>Wed, 13 Apr 2022 14:51:02 +0800</pubDate><description><![CDATA[Undo日志
redo log是事务持久性的保证，undo log是事务原子性的保证。在事务中 更新数据 的 前置操作 其实是要先写入一个 undo log 。
如何理解Undo日志
事务需要保证 原子性 ，也就是事务中的操作要么全部完成，要么什么也不做。但有时候事务执行到一半
会出现一些情况，比如：

情况一：事务执行过程中可能遇到各种错误，比如 服务器本身的错误 ， 操作系统错误 ，甚至是突
然 断电 导致的错误
情况二：程序员可以在事务执行过程中手动输入 ROLLBACK 语句结束当前事务的执行。

]]></description><category></category></item><item><title><![CDATA[MySQL事务日志之redo日志]]></title><link>https://blog.youkuaiyun.com/small_engineer/article/details/124102287</link><guid>https://blog.youkuaiyun.com/small_engineer/article/details/124102287</guid><author>small_engineer</author><pubDate>Tue, 12 Apr 2022 14:39:49 +0800</pubDate><description><![CDATA[事务有4种特性：原子性、一致性、隔离性和持久性。那么事务的四种特性到底是基于什么机制实现呢？

事务的隔离性由 锁机制 实现。
事务的原子性，一致性，持久性由事务的redo日志和undo日志来保证
redo log称为重做日志，提供再写入操作，恢复提交事务修改的页操作，用来保证事务的持久性
undo log称为回滚日志，回滚行记录到某个特定版本，用来保证事务的原子性，一致性

redo日志
redo的组成
重做日志缓存保存在内存中，是易失的
重做日志文件保存在硬盘中，是持久的
redo流程


第1步：先将]]></description><category></category></item></channel></rss>