L1、L2、L3、内存要了解cache的缓存一致性和伪共享问题,就要先了解L1 cache 、L2 cache 、L3 cache和内存之间的关系。
通常cpu内有3级缓存,即L1、L2、L3缓存。其中L1缓存分为数据缓存和指令缓存,cpu先从L1缓存中获取指令和数据,如果L1缓存中不存在,那就从L2缓存中获取。每个cpu核心都拥有属于自己的L1缓存和L2缓存。如果数据不在L2缓存中,那就从L3缓存中获取。而L3缓存就是所有cpu核心共用的。如果数据也不在L3缓存中,那就从内存中获取了。当然,如果内存中也没有那就只能从硬盘中获取了。
为什么要设计成这个样子呢?因为从不同的设备中获取数据的耗时是不一样的。
设备(模块)
硬件类型
成本(美元/MB)
通常大小
随机读取耗时
L1 cache
SRAM
7
几十到几百KB
2~4个周期 1纳秒左右
L2 cache
SRAM
7
几百KB到几MB
10~20个周期 5纳秒左右
L3 cache
SRAM
7
几MB到几十MB
20~60个周期 10纳秒左右
内存
DRAM
0.015
几GB至几十GB
2 ...
mysql事务控制并发事务并发事务会带来一些问题
脏读一个事务读取到了另一个事务修改但未提交的数据。
不可重复读一个事务中多次读取同一行记录不一致。
幻读一个事务中多次按相同条件查询,结果不一致。(多了或者少了)
事务隔离级别
事务隔离级别
脏读
不可重复读
幻读
读未提交
会发生
会发生
会发生
读已提交
×
会发生
会发生
可重复读
×
×
会发生
串行化
×
×
×
注意mysql的MVCC解决了部分幻读问题(不能解决当前读下的幻读)。
事务并发问题主要是解决读读、读写、写写之间的问题。加排它锁性能太低。使用读写锁能解决读读之间性能问题,但是无法解决读写之间的性能。
MVCCMVCC使用了Copy On Write的思想。可以支持读读并行,也可以支持读写并行。写写依旧无法并行。
概念MVCC(Multi Version Concurrency Control)被称为多版本控制。在数据库中为了实现高并发数据访问,对数据进行多版本处理,并通过事务的可见性来保证事务能看到自己应该看到的数据版本。
MVCC最大的好处是读不加锁,读写不冲突,这对读多写少 ...
背景关于mysql的B+树,经常会遇到有关的这么几个问题:
B+树索引是什么?
为什么B+树(比B树)更适合做数据库索引?
为什么B+树索引一页是16k?
为什么建议主键自增?
为什么不建议存储text等大类型?或者建议拆分表来存储?
为什么联合索引左匹配?
正文B+树索引是什么?
B+树需要满足以下几个要求:
从根节点到叶节点的所有路径都具有相同的长度。
所有数据信息存储在叶子节点,非叶子节点仅作为叶子节点的索引存在。
根节点至少拥有2个子树。
每个树节点最多拥有M个子树
每个节点(除了根节点)拥有至少M/2个子树。
为什么B+树更适合做数据库索引?
B+树层高比较低,在搜索时能够减少磁盘读取次数。
B+树(聚簇索引)数据存储在叶子节点,搜索完成的时候就能一次取出所有数据,避免额外磁盘读取。(磁盘预读)
B+树非叶子节点仅存储索引数据,大大减小数据量,可以一次读取到内存中(单个节点)。
B+树索引在叶子节点存在双向链表,可以支持范围查询、扫表。
为什么B+树索引一页是16k?从磁盘的物理结构来看存取信息的最小单位是扇区,一个扇区是512字节。从操作系统对硬盘的存取 ...
什么是AQS?
AQS全称是AbstractQueuedSynchronizer ,java中的一个抽象类,AQS定义了一套多线程访问共享资源的同步框架。
许多同步类的实现都依赖于它,例如ReentrantLock/Semaphore/CountDownLatch。
原理基本原理
AQS维护了一个共享资源(state,使用volatile修饰的int变量)和一个FIFO线程等待队列。AQS只是一个框架,具体资源的获取/释放方式交由自定义同步器去实现。独占模式下只用实现 tryAcquire-tryRelease ,而共享模式下只用实现tryAcquireShared-tryReleaseShared
同步器需要实现的主要方法:
isHeldExclusively(): 该线程是否正在独占资源。
tryAcquire(int): 独占方式,尝试获取资源,成功则返回true,失败则返回false。
tryRelease(int): 独占方式,尝试释放资源,如果释放后线程不再占用该资源,其他线程可以抢占资源则返回true,否则返回false。
tryAcqu ...
什么是分布式共识?假设我们有一个单节点系统,这个系统用于存储一个值。
我们还有一个可以向服务器发送值的客户端。
图中左侧绿色的圆代表客户端,右侧蓝色的圆代表单节点存储系统,用于存储一个值x。
客户端发送一个数值(8)给服务端,服务端存储这个值。
只有一个节点的系统,很容易达成系统共识。但如果我们有多个节点,我们如何达成共识呢?
这就是分布式共识问题。
Raft是一种实现分布式共识的协议。
Raft是如何工作的?一个阶段有3种不同的状态:Follower(追随者)Candidate(候选人)Leader(领导者)。
一开始所有节点都是Follower。
如果Follower没有得到Leader的心跳,那么他们可以成为Candidate。
图中节点a变成Candidate。
Candidate给其他节点发送请求投票,其他节点将投票回应。
Candidate得到了大多数节点的投票,就会变成Leader。这个过程被称为领导者选举。
现在系统的所有更改都必须经过Leader。
每一个更改都会被记录一条节点日志,这个修改暂时不会被提交,值不会被系统设置。要提交这个修改,需要节点把 ...
前言mysql在大数据量的情况下使用limit分页,会随着页码增大而查询效率低下。该怎么优化呢?
先看是不是,再看为什么,最后看怎么办
准备mysql本次操作使用mysql8
表为了验证大数据量,我们先准备一张5000万条记录的表。
1234567891011CREATE TABLE `demo_5000` ( `id` bigint NOT NULL AUTO_INCREMENT, `a` int NOT NULL, `b` int NOT NULL, `c` int NOT NULL, `d` varchar(45) NOT NULL, `f` varchar(45) NOT NULL, `g` varchar(45) NOT NULL, PRIMARY KEY (`id`), KEY `idx_combo` (`a`,`b`,`c`)) ENGINE=InnoDB AUTO_INCREMENT=50010007 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
一张简单的表,主键自增,3个int字段和3 ...
dobbo中目前支持的RPC协议对比
协议
链接个数
链接方式
传输协议
传输方式
序列化
适用范围
适用场景
dubbo
单连接
长连接
TCP
NIO异步传输
hessian二进制序列化
传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用 dubbo 协议传输大文件或超大字符串。
常规远程服务方法调用
http
多连接
短连接
HTTP
同步传输
表单序列化
传入传出参数数据包大小混合,提供者比消费者个数多,可用浏览器查看,可用表单或URL传入参数,暂不支持传文件。
需同时给应用程序和浏览器 JS 使用的服务。
hessian
多连接
短连接
HTTP
同步传输
Hessian二进制序列化
传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件。
页面传输,文件传输,或与原生hessian服务互操作
rmi
多连接
短连接
TCP
同步传输
java标准二进制序列化
传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件。
常规远程服务方法调用,与原生RMI服务互操作
dubbo ...
程序人生
未读背景当用户通过浏览器从服务器上下载一个文件时,服务器具体是怎么处理这个文件的呢?大致可以分为以下几步:
应用程序产生一个指定去读取需要的文件。
由于读取磁盘文件涉及到硬件,所以进程陷入内核态。
操作系统检查内核空间是否有文件缓存,有就直接把数据拷贝到用户空间。
如果没有,系统则通过磁盘读取数据,放入内核空间。
系统再将内核空间的数据复制到用户空间,最后切换会用户态,交由应用程序处理。
应用程序拿到数据后调用网络输出(输出流)。
由于网络输出涉及到硬件,所以进程陷入内核态。
由操作系统把应用程序的数据拷贝至内核空间(网络输出缓冲)。
由操作系统把内核空间的数据拷贝至网卡。
操作系统将进程切回用户态。
由此我们可以看到,这个文件数据一共经历了四次数据拷贝。数据拷贝需要CPU的参与(DMA处理除外),并且程序在用户态和内核态发生了多次上下文切换,增加了cpu负担。如果使用DMA来处理硬件拷贝,那这种处理方法仍旧有2次数据拷贝使用到了CPU。
零拷贝 zero-copy什么是零拷贝?就是避免cpu参与这种数据拷贝,让数据传输不经过用户空间。零拷贝适用于不对数据进行修改、过滤等处理的场景, ...
httpsHTTP 有以下安全性问题:
使用明文进行通信,内容可能会被窃听;
不验证通信方的身份,通信方的身份有可能遭遇伪装;
无法证明报文的完整性,报文有可能遭篡改。
HTTPS 并不是新协议,而是让 HTTP 先和 SSL(Secure Sockets Layer)通信,再由 SSL 和 TCP 通信,也就是说 HTTPS 使用了隧道进行通信。
通过使用 SSL,HTTPS 具有了加密(防窃听)、认证(防伪装)和完整性保护(防篡改)。
加密对称密钥加密对称密钥加密(Symmetric-Key Encryption),加密和解密使用同一密钥。
优点:运算速度快;
缺点:无法安全地将密钥传输给通信方。
非对称密钥加密非对称密钥加密,又称公开密钥加密(Public-Key Encryption),加密和解密使用不同的密钥。
公开密钥所有人都可以获得,通信发送方获得接收方的公开密钥之后,就可以使用公开密钥进行加密,接收方收到通信内容后使用私有密钥解密。
非对称密钥除了用来加密,还可以用来进行签名。因为私有密钥无法被其他人获取,因此通信发送方使用其私有密钥进行签名,通信接收方使用 ...
基础知识概述
Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存储键和五种不同类型的值之间的映射。
键的类型只能为字符串,值支持五种数据类型:字符串、列表、集合、散列表、有序集合。
Redis 支持很多特性,例如将内存中的数据持久化到硬盘中,使用复制来扩展读性能,使用分片来扩展写性能。
数据类型
可以存储的值
操作
STRING
字符串、整数或者浮点数
对整个字符串或者字符串的其中一部分执行操作对整数和浮点数执行自增或者自减操作
LIST
列表
从两端压入或者弹出元素 对单个或者多个元素进行修剪, 只保留一个范围内的元素
SET
无序集合
添加、获取、移除单个元素 检查一个元素是否存在于集合中 计算交集、并集、差集 从集合里面随机获取元素
HASH
包含键值对的无序散列表
添加、获取、移除单个键值对 获取所有键值对 检查某个键是否存在
ZSET
有序集合
添加、获取、删除元素 根据分值范围或者成员来获取元素 计算一个键的排名
与memcached 区别
数据类型
memcached仅支持字符串类型,而redis支持更多的数据类型 ...
背景现在越来越多的网站开始使用https协议。相较于http协议,https能够加密浏览器和服务端之间的通信,防止通信数据遭他人窃取和串改。
静态网站也需要启用https吗?静态网站是什么呢?那些只有html的静态网页组成的网站,基本上和服务器没有什么交互。客户端也不会发送账户名、密码、表单等各种数据给服务端。如此一来就有了上面的疑问,既然是静态的,几乎没有动态数据交互,那还用得着https吗?
但仔细一想,答案非常的明显:也是需要的!
我们可以看看常见的一些静态网页,例如w3school不也启用了https嘛。静态网站虽然没有动态数据交互,也就不存在通信数据遭他人窃取了,但是依然存在串改的可能。劫持者可以在你的静态网页上修改数据,嵌入广告或者钓鱼链接。所以还是有必要启用https的。
准备工作证书个人网站要启用https,首先需要准备证书。这是https协议中的一部分,具体原理不在这里详细说明了。通常可以有2种途径弄到证书。
第一种是自己生成。但是自己生成的证书很多浏览器都不认,会给出警告提示。虽然忽略警告就可以继续使用https和网站进行通信了,不过现在不是一个完美的解决方案。
...
程序人生
未读写时拷贝
在数据第一次写入到某个存储位置时,首先将原有内容拷贝出来,写到另一位置处,然后再将数据写入到存储设备中,该技术只拷贝在拷贝初始化开始之后修改过的数据。
linux中的cow在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,linux中引入了“写时复制“技术,也就是只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。
在fork之后exec之前两个进程用的是相同的物理空间(内存区),子进程的代码段、数据段、堆栈都是指向父进程的物理空间,也就是说,两者的虚拟空间不同,但其对应的物理空间是同一个。当父子进程中有更改相应段的行为发生时,再为子进程相应的段分配物理空间,如果不是因为exec,内核会给子进程的数据段、堆栈段分配相应的物理空间(至此两者有各自的进程空间,互不影响),而代码段继续共享父进程的物理空间(两者的代码完全相同)。而如果是因为exec,由于两者执行的代码不同,子进程的代码段也会分配单独的物理空间。
在网上看到还有个细节问题就是,fork之后内核会通过将子进程放在队列的前面,以 ...
其实也就是用到了回溯算法。
回溯算法也叫试探法,它是一种系统地搜索问题的解的方法。回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。
首先定义一个Sudoku类,用来保存和处理9*9的数组
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108import java.util.ArrayList;import java.util.List;/** * Created shellingford on 2017/3/4. */public class Sudoku { private int[][] src; private List<IRule> ru ...
程序人生
未读背景需求当拥有自己的云服务器、树莓派等软硬件时,总会希望在特定事件产生时收到一些推送消息给自己。例如无屏幕的树莓派开始时发送IP信息给自己;云服务器流量、cpu高峰时发送警告消息给自己。
要求
采用方便快捷的消息接收方式:微信。(邮件可能不及时,其他推送又需要安装多余的app,反正手机上装了微信,就用微信的信息推送)
没有推送条数、推送内容上的限制。(消息要提前生成模板审核?不存在的!)
利用手上的资源(云服务器一个),没有额外的费用。(例如消息推送费用)
别人的服务在寻找类似的推送服务时,看到了server酱。接入方便,使用上符合要求1 。不过由于vip制度的关系,存在一些费用,又无法做定制化的处理。所以便希望自己搭建一套简单易用的推送服务来。
自建服务原理微信、无认证的微信公众号都不提供针对个人定制化的消息推送功能。所以只能绕道企业微信来实现了。企业微信拥有推送API,并且允许成员通过微信来接收企业微信的消息。如此一来我们就可以通过企业微信进行消息推送,通过微信来接收消息,整个使用过程中并不需要手机安装企业微信APP。
准备资源个人云服务器
云服务器或者虚拟空间都可以。
云服务 ...
前言使用hexo搭建博客之后遇到的第一个不便就是发布,每次都需要在本地生成静态文件后使用ftp上传服务器,有时候改变的文件又非常的多,全部上传一遍太麻烦了。于是开始考虑自动化脚本处理这些。
解决方案
上传码云
首先,自己写的文章和设置的配置都需要上传代码托管服务器,以防万一,也是一种备份。我这里使用的就是码云,免费的功能足够是用了。
接着码云上有WebHooks,可以使用hook触发服务器,并执行自动更新网站。
触发服务器
这里已php为例,为了安全可以校验秘钥。
12345678910111213<?php$headers = getallheaders();$gitee_token = $headers["X-Gitee-Token"];$gitee_timestamp =$headers["X-Gitee-Timestamp"];echo "gitee_token: $gitee_token <br />\n";echo "gitee_timestamp: $gitee_timest ...
前言个人博客已有好几年没有更新了,有工作忙的原因,也有自己比较懒的原因。看了看之前的博客程序,使用的是emolog5,好久远的程序了,主题的作者也不维护了。考虑再三,决定彻底重建个人博客。
需求既然是重建博客就涉及到需要选择博客程序,什么样的程序比较好呢?对于这个问题,还是需要先看看自己的需求。
写写自己的文章,最好能使用markdown格式书写。
能有好看点的主题。
对服务器要求比较低,使用php或者静态网站。
最好能播放音乐,并且是那种无中断的。
选择程序最先考虑的还是emlog,毕竟之前就使用了这点,而且最新版的emlog pro版本支持markdown书写文章。然而比较可惜的是,之前喜欢的主题不支持这个版本,并且作者也不再维护了。加之,pro版本的商城中主题也不多,并且全都不支持pjax,使得在跳转的时候播放音乐中断。
之前也用过zblog,现在搜索了一下,发现zblog的域名解析都没了,感觉也是办不下去了吧。
最后发现了hexo这个程序,支持markdown书写,最后生成的是html静态文件,对服务器要求最低。在github上也搜索到了一个叫hexo-theme-bamb ...