普通视图

发现新文章,点击刷新页面。
昨天以前vzard's blog

二叉搜索树的一些性质

作者 vzardlloo
2020年9月22日 01:38

二叉搜索树的中序遍历的结果序列是一个递增排序的序列。

中序遍历的顺序是:左节点 - 根节点 - 右节点

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
result := make([]*Node,0)
func inorder(root *Node) {
if root == nil {
return
}

inorder(root.Left)
result = append(result,root)
inorder(root.Right)

return
}

二叉搜索树的后继节点

即比当前节点大的最小节点,主要思路:取改节点的右节点,然后一直取左节点直到左节点为空,最后指向的就是该节点的后继节点

示例代码:

1
2
3
4
5
6
7
func Successor(node *Node) *Node {
succ := node.Right
for succ.Left != nil {
succ = node.Left
}
return succ
}

二叉搜索树的前驱节点

即比当前节点小的最大节点,主要思路:取改节点的左节点,然后一直取右节点直到右节点为空,最后指向的就是该节点的前驱节点

示例代码:

1
2
3
4
5
6
7
func Predecessor(node *Node) *Node {
pre := node.Left
for pre.Right != nil {
pre = pre.Right
}
return pre
}

redis的事务

作者 vzardlloo
2020年9月11日 01:07

什么是事务

事务是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。它有4个特性:

  • 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行[3]
  • 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束[3]
  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行[3]
  • 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中[3]

Redis的事务

Redis如何开启事务

redis开启事务主要有如下4个命令:MULTIEXECDISCARDWATCH

命令作用
MULTI显式的开启事务,之后的命令将被缓存在命令队列里面,入队的时候会对命令进行检查,命令错误就入队失败,直到使用EXEC命令才一起执行,
EXEC执行事务中的commands队列,恢复连接状态。如果在watch之前被调用,只有监测中的Keys没有被修改,命令才会被执行,否则停止执行
DISCARD清空事务中的commands队列,恢复连接状态,如果有使用watch命令监控key的话,监控状态将被取消
WATCH将给出的Keys标记为监测态,作为事务执行的条件,一旦一个被监控的键被改了,事务将执行失败

Redis事务是真正的事务么?满足ACID么?

  • 原子性:redis通过commands队列的实现,要么队列里面的全部执行要么全部不执行,这个满足原子性。值得注意的是,redis在执行队列里面的命令在执行的时候有某一条发生错误的时候,redis并不会进行回滚(rollback),官方解释是:

    • Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
    • 因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。

    鉴于没有任何机制能避免程序员自己造成的错误, 并且这类错误通常不会在生产环境中出现, 所以 Redis 选择了更简单、更快速的无回滚方式来处理事务。

  • 一致性:redis有三个地方有可能执行事务出错,redis都进行了妥善的处理保证其一致性。

    • 入队错误:在命令进入commands队列的时候,会检查命令的合法性,发现错误,不允许入队列,命令不会执行,所以不会导致一致性问题。

    • 执行错误:命令执行期间报错的时候,错误的命令不会对数据库进行任何改动,所以不会导致一致性问题。

    • 服务器挂了:没有开启持久化,重启后是个空的数据库,可以达到一个新的一致的状态;开了RDB或者AOF持久化,可以将数据库恢复到一个一致性的状态。

  • 隔离性:redis服务器总是单线程执行事务并且不会被中断,即事务总是串行执行的,A事务执行完才会执行B事务,所以没有隔离性的问题。

  • 持久性:redis的事务只是简单的将一堆redis命令打包到一个队列里面,没有任何额外的持久化保证,所以redis事务的持久化要依赖redis使用的持久化机制。

    • 未开启持久化:redis没法进行持久化,不能保证持久性

    • RDB模式: RDB模式要在某种触发条件下才会进行持久化操作,所以没法保证持久化。

    • AOF模式:需要看appendfsync参数具体的值,如果是alway 则每次执行命令都会进行持久化操作,那么可以保证持久化,在everysecno的情况下没法保证持久化。

​ 黑魔法: 事务里面最后一句加个save命令可以保证持久性,但是效率比较低下

总结

redis支持事务,在一定的配置下满足事务的ACID四个特性,但是又和传统关系性数据库的事务有所区别。

redis数据类型及使用场景

作者 vzardlloo
2020年9月8日 00:46

Redis的数据类型

数据类型对应编码方式

数据类型编码方式
Stringrawembstrint
Hashhashtableziplist
Listlinkedlistziplistquicklist
Sethashtableintset
Zsetskiplistziplist

编码类型对应数据结构

编码方式数据结构
raw动态字符串编码
embstr优化内存分配饿字符串分配
int整数编码
hashtable散列表编码
ziplist压缩列表编码
linkedlist双向链表编码
quicklist快速列表编码
intset整数集合编码
skiplist跳跃表编码

使用场景

数据类型使用场景
String普通的k-v缓存,分布式锁
Hash字典结构,比如缓存一个创意的消耗信息,创意id对应曝光数、点击数等多个subkey
List关注列表,简单的队列
Set去重器,集合运算
Zset排行榜,优先级队列

灵魂七问

作者 vzardlloo
2020年8月22日 01:14
  • 你为什么做这个东西?

  • 它和其他东西有什么不同?

  • 你可以做些什么,比起其他的呢?

  • 你是怎么实现的?

  • 实现过程中的核心问题是如何解决的,解决方案是一种么?为什么你这么选择?

  • 你对你做的这个东西还有什么规划?

  • 你如何看待你做的东西所处领域的发展?

统计知识(1)

作者 vzardlloo
2017年10月16日 16:44

前言

最近为了参加一个数据分析比赛,在复习统计这块的知识。首先什么是统计呢?我采用北京大学出版社出版的《应用经济统计学》中的定义:统计学是一门对群体现象数量特征进行计量描述和分析推论的科学。从定义可以看出统计学主要干两件事一个是对群体现象特征进行计量描述,第二个是对群体数量进行分析得出推论。那我们一件一件事来,先来讲一下统计学干的第一件事:对群体现象特征进行计量描述。本文主要理一下脉络,对于细节不过多纠结(主要是Markdown打公式太麻烦……)

描述集中趋势的计量

算数平均数

  • 简单算数平均数
    简单算数平均数就是一组数据N个数值的和除以N。
  • 加权算数平均数
    每个数值的权重乘以数值的和除以数据个数。

缺点:容易受极端值影响

中位数

将一组数据排序,处在数据中点位置的数值就是中位数。(位置平均数)

优点:稳健,不收极端值影响
缺点:缺乏敏感性,不适合代数运算

众数

一组数据中出现次数最多的数值。

优缺点:和中位数一样

三者的关系

我们知道如果一直增加观察项数,同时又缩小组距,那么分布的直方图就接近一条光滑的曲线。按这条曲线来解释的话,均值是数据分布的平衡点或者说是中心,中位数把这个分布划分为两半,众数
正好是分布顶端的数值。并且在对称分布中三个测度重合,斜分布中三个测度分离。

其他测度

1.分位数
中位数的推广,中位数可以看做二分位数,同样也有四分位数,十分位数,N分位数…
2.几何平均数
变量X的n项观察值x_1,x_2,x_3…x_n的乘积的n次根。
3.调和平均数
一组观测值的倒数的算数平均数的倒数。

描述离中趋势的计量

极差

一组观测数据中最大值与最小值的差。表现数据的变动范围。

平均差

一组数据值与其均值之差的绝对值的和的平均值。

方差

一组资料中各数值与其算数平均数离差平方的平均数。

标准差

标准差的平方就是方差

Chebishev定理

对于任何一组资料,观测值落于均值左右k个标准差的区间内的比例至少为(1-1/k^2).

四分位差

四分位差是第三个四分位值于第一个四分位值之差的二分之一。实际就是一组资料中间一半观测值的极差。

异众比率

非众数值的次数之和占总次数之比重。

平均差系数

平均差于均值之比。

同步Github上的fork

作者 vzardlloo
2017年10月13日 15:08

我们有时候会在Github上fork一个我们感兴趣的项目到自己的仓库,等一段时间过后这个项目已经更新了,但是自己仓库里还停留在刚fork时的状态,那么我们如何把自己fork到仓库的项目同步到作者的进度呢?这篇博客主要就是讲一下这个问题。
这个问题我有两种解决的办法:
一种是在Github上操作,把自己仓库的项目设成base,把作者的的项目设成head,然后给自己提pr,最后在pull下来就行了。这种方法的缺点就是要开网页点来点去,如果你正在沉迷在命令行里无法自拔可能不太喜欢这种方法。

第二种方法是在把作者的项目添加为自己的远程分支,然后需要同步的时候fetch一下这个远程分支,然后切换的本地分支(如果不在的话),然后把远程仓库合并到本地分支。具体方法如下:

  • 先查看一下自己的远程分支:

    1
    2
    3
    git remote -v
    # origin https://github.com/YOUR_USERNAME/YOUR_FORK.git (fetch)
    # origin https://github.com/YOUR_USERNAME/YOUR_FORK.git (push)
  • 如果作者的仓库不在远程分支中,则把他添加到远程分支:

    1
    git remote add upstream https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git
  • 再次查看远程分支情况,确保已经加入:

    1
    2
    3
    4
    5
    git remote -v
    # origin https://github.com/YOUR_USERNAME/YOUR_FORK.git (fetch)
    # origin https://github.com/YOUR_USERNAME/YOUR_FORK.git (push)
    # upstream https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git (fetch)
    # upstream https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git (push)
  • 从上游仓库 fetch 分支和提交点,传送到本地,并会被存储在一个本地分支 upstream/master

    1
    2
    3
    4
    5
    6
    7
    git fetch upstream
    # remote: Counting objects: 75, done.
    # remote: Compressing objects: 100% (53/53), done.
    # remote: Total 62 (delta 27), reused 44 (delta 9)
    # Unpacking objects: 100% (62/62), done.
    # From https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY
    # * [new branch] master -> upstream/master
  • 切换到本地主分支(如果不在的话)

    1
    2
    git checkout master
    # Switched to branch 'master'
  • 把 upstream/master 分支合并到本地 master 上,这样就完成了同步,并且不会丢掉本地修改的内容。

    1
    2
    3
    4
    5
    6
    7
    8
    git merge upstream/master
    # Updating a422352..5fdff0f
    # Fast-forward
    # README | 9 -------
    # README.md | 7 ++++++
    # 2 files changed, 7 insertions(+), 9 deletions(-)
    # delete mode 100644 README
    # create mode 100644 README.md
  • 同步到Github上的自己的项目

    1
    git push origin master

OK,这个小问题都到此结束!

Http协议杂谈

作者 vzardlloo
2017年9月19日 16:42

HTTP的特性

  • HTTP构建于TCP/IP协议之上,默认端口号是80
  • HTTP是无连接无状态的

HTTP报文

Http协议是以ASCII码传输,建立在TCP/IP协议之上的应用层规范。规范把HTTP请求分为三个部分:状态行、请求头、消息主题。类似于下面这样:

1
2
3
4
5
6
7
8
9
10
11
12
GET /en-US/docs/Web/HTTP/Headers/Content-Disposition HTTP/1.1
Host: developer.mozilla.org
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Mobile Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: https://hit-alibaba.github.io/interview/basic/network/HTTP.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.8
Cookie: csrftoken=0QVKqjybZR4MatNi0vCP03XIDrEWODO9; dwf_section_edit=True; dwf_sg_task_completion=False; _ga=GA1.2.817713072.1498834189; _gid=GA1.2.1652928103.1505806097
If-None-Match: "76da2643e0174c564b0a898793e76edda496498f"

HTTP定义了于服务器交互的不同方法,最基本的方法有4中,分别是GET,POST,PUT,DELETEURL全称是资源描述符,我们可以这样认为:一个URL地址,它用于
描述一个网络上的资源,而HTTP中的GET,POST,PUT,DELETE就对应着对这个资源的查,增,改,删4个操作。

  1. GET用于信息获取,而且应该是安全的 和 幂等的。
    所谓安全的意味着该操作用于获取信息而非修改信息。换句话说,GET 请求一般不应产生副作用。就是说,它仅仅是获取资源信息,就像数据库查询一样,不会修改,增加数据,不会影响资源的状态。
    幂等的意味着对同一URL的多个请求应该返回同样的结果。

GET请求报文示例:

1
2
3
4
5
GET /books/?sex=man&name=Professional HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive

  1. POST表示可能修改变服务器上的资源的请求。
1
2
3
4
5
6
7
8
9
POST / HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 40
Connection: Keep-Alive
sex=man&name=Professional
  1. 注意:
    • GET 可提交的数据量受到URL长度的限制,HTTP 协议规范没有对 URL 长度进行限制。这个限制是特定的浏览器及服务器对它的限制
    • 理论上讲,POST 是没有大小限制的,HTTP 协议规范也没有进行大小限制,出于安全考虑,服务器软件在实现时会做一定限制
    • 参考上面的报文示例,可以发现 GET 和 POST 数据内容是一模一样的,只是位置不同,一个在URL里,一个在 HTTP 包的包体里

POST提交数据的方式

HTTP 协议中规定 POST 提交的数据必须在 body 部分中,但是协议中没有规定数据使用哪种编码方式或者数据格式。实际上,开发者完全可以自己决定消息主体的格式,只要最后发送的 HTTP 请求满足上面的格式就可以。

但是,数据发送出去,还要服务端解析成功才有意义。一般服务端语言如 php、python 等,以及它们的 framework,都内置了自动解析常见数据格式的功能。服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。所以说到 POST 提交数据方案,包含了 Content-Type 和消息主体编码方式两部分。下面就正式开始介绍它们:

application/x-www-form-urlencoded

这是最常见的POST数据提交方式。浏览器的原生

表单,如果不设置entype属性,那么最终就会以application/x-www-form-urlencoded方式提交数据。上个小节当中的例子便是使用了这种提交方式。可以看到 body 当中的内容和 GET 请求是完全相同的。

响应报文

HTTP 响应与 HTTP 请求相似,HTTP响应也由3个部分构成,分别是:

  • 状态行
  • 响应头
  • 响应正文

状态行由协议版本、数字形式的状态代码、及相应的状态描述,各元素之间以空格分隔。

常见的状态码有如下几种:

  • 200 OK 客户端请求成功
  • 301 Moved permanently 请求永久重定向
  • 302 Moved Temporarily 请求临时重定向
  • 304 Not Modified 文件未修改,可以直接使用缓存的文件
  • 400 Bad Request 由于客户端请求有语法错误,不能被服务器所理解
  • 401 Unauthorized请求未经授权。这个状态代码必须和WWW-Authenticate报头域一起使用
  • 403 Forbidden 服务器收到请求,但是拒绝提供服务。服务器通常会在响应正文中给出不提供服务的原因
  • 404 Not Found 请求的资源不存在,例如,输入了错误的URL
  • 500 Internal Server Error 服务器发生不可预期的错误
  • 503 Server Unavailable 服务器当前不能处理客户端的请求,一段时间后可能恢复正常

下面是一个HTTP响应的例子:

1
2
3
4
5
6
7
HTTP/1.1 200 OK
Server:Apache Tomcat/5.0.12
Date:Mon,6Oct2003 13:23:42 GMT
Content-Length:112
<html>...

修复hexo博客的一个bug

作者 vzardlloo
2017年8月25日 18:18

之前不小心把JAVA分类写成了java发布了,然后又改了回来,并且手动地在博客public/categories/.deploy_git/categories/下的java文件夹改成JAVA重新发布,结果在点击JAVA分类时会报404。经过一番研究我发现虽然我本地都将java改成了JAVA,但是GitHub仓库里的文件夹名称还是java。对比“java”和“JAVA”我猜测可能是git大小写不敏感所以JAVA并没有覆盖掉java,谷歌一下果然如此。由于我把java改成了JAVA所以在网页点击”分类”时访问的是:https://xxxxxxxx/JAVA/,而GitHub仓库里依然是java,只能访问https://xxxxxxxxxx/java/,由于http协议对于URL是大小写敏感的,所以访问https://xxxxxxxx/JAVA/必然会报404。找到问题所在下面开始修复bug:

  1. 进入.deploy_git文件夹,输入git config core.ignorecase false把忽略大小写
    关闭。(必须要进入.deploy_git执行命令,因为只有这个文件夹是git仓库,这里的文件才会推送到GitHub仓库)
  2. 回到博客根目录,执行hexo d重新发布博客

执行完毕,bug修复!

❌
❌