一致性哈希算法

一致性hash算法在分布式系统里面使用比较广,我也只是听说过这个概念,今天看到一个一致性hash开源库,随手写篇文章,记录下吧。

假如我们使用普通的哈希方式来处理负载均衡,到目标机器的映射使用的算法为:

hash(o) mod n (n表示机器的总数)

如果需要增加或减少一台机器的时候,算法就变为 hash(o) mod (n + 1) / hash(o) mod (n - 1)

不仅需要重新编写代码,当服务器做了大量变更,大量的o会重定向不同的服务器而导致了缓冲不被命中,所以此时,就提出了一致性hash算法。

一致性哈希算法

简单的说,哈希函数将o映射到 0 ~ 2^32 - 1的值区间,将这些数字头尾相连,然后将它们组织成一个闭合的圆环。如图一所示:

要实现一致性哈希算法,思路就是下面2个步骤:

Read More

写了一个简单的CGI Server

之前看过一些开源程序的源码,也略微知道些Apache的CGI处理程序架构,于是用了一段时间,用C写了一个简单的CGI Server,代码算上头文件,一共1200行左右,难度中等偏上。麻雀虽小,五脏俱全。如果把程序里所涉及的HTTP协议,Linux下POSIX编程等等搞清楚,我想找工作中肯定是有足够的竞争力的,当然我也只是皮毛而已,不再班门弄斧了,下面简单的说下程序流程吧。

再说程序流程之前,我先简单说下CGI吧,CGI这个东西比较老了,N年之前,没有PHP JSP等等动态脚本之前,这个是非常火的。只要能支持输入输出的程序,都可以编写CGI脚本,比如Apache就集成了CGI服务器功能,你可以使用Python编写简单的CGI脚本,可以参照前几天我发的文章,点击此处,现在CGI 脚本基本上使用的比较少了,但是在一些对效率要求比较高的设计里还是可以看到一些身影,比如腾讯的QQ相册,QQ空间里就可以看到(你可以打开QQ空间,查看源码-查找CGI),他们的脚本应该是C/C++编写的,效率,你懂的,如果你想更多的了解CGI脚本相关,可以点击此处,推荐了解一些,但是不值得深入学习,那个精力不如学习PHP/Python了。。。

其实说白了,CGI 扮演的就是在服务器和特定解释器之间输入输出协议的角色,每个来自用户的请求,Web服务器都会唤起特定语言解释器的命令行,执行CGI脚本。

现在来介绍下此CGI Server,我不想长篇大论了,一幅图来描述其执行过程(字比较丑,凑合看吧),具体看代码吧:

Read More

Redis里dict源码剖析

Redis全名叫做Remote Dictionary Server,从全称就可以看出dict是Redis里重要的数据结构,看了下dict.c里的源码,简单分析下。

dict.c主要是实现了哈希功能,实际上实现哈希(字典)常见的方法有几种:

<1>比如我们数据结构课上学的数组和链表法,但是这种方法适用于元素个数不多的情况下

<2>使用复杂的平衡树(B-等等),性能比较不错,比如MySQL里的索引就使用了这种方法

<3>哈希表,兼顾了高效和简单性,Redis选择了这种方法。

我们就解读下dict.c里源码里的数据结构吧,我们知道hash表的性能由hash表的大小和解决冲突的方法决定。Redis里使用了两个哈希表(ht[0])和哈希表(ht[1]),hash[0]是字典主要使用的hash表,而hash[1]主要对0号哈希表进行rehash时才使用。读者可能不明白这个地方啥意思?其实就是,程序每次申请几个字节(默认为4字节),当key/value数量达到规定时,程序申请的4字节就翻一倍(这里使用了慢迁移),那什么时候rehash呢?我们知道size == used(根据下面的dictht结构体)时,达到最理想状态,所以当used/size > 1时,就进行rehash。我们先看看dict.h里定义的几个结构体吧:

Read More

Letter Combinations of a Phone Number

由于这个月还没写博客,找道题应付下吧,主要原因是自己现在太忙了,得准备找工作啊,唉,弱的惨不忍睹。好吧,不抱怨了,进入正题,LeetCode上面的一道题,题目描述为:

Given a digit string, return all possible letter combinations that the number could represent.

A mapping of digit to letters (just like on the telephone buttons) is given below.

**Input:**Digit string "23"
**Output:** ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
**
Note:**
Although the above answer is in lexicographical order, your answer could be in any order you want.

其实就是组合问题,如下图所示:

如图所示,遍历完 1,2,3,就把a,d (g,h,i)遍历完了,之后回溯到e,就是个DFS搞定。

Read More

使用python编写简单网络爬虫技巧总结

使用python写过几个小玩具,基本上都与爬虫、Web相关的,自己也积累了下经验,也看过很多文章,一直想总结下,可惜现在要忙于找工作,实验室活也比较多,也就落下了。感觉如果时间长不记录,也就懒散了,并且许多东西我写完过个两天,我自己都记不住当时怎么想的了。

0、HTTP协议

基本上常见的Web开发里,Web内容都是通过HTTP协议进行传输的(虽然咱不懂Web开发,但是基本的计算机网络知识还是了解的),通过TCP连接服务器的80端口,爬虫其实质就是通过模拟浏览器发送HTTP请求,至于HTTP请求相关知识,点击这里

1
2
3
4
HTTP通常通过创建到服务器80端口的TCP连接进行通信
HTTP协议的内容包括请求方式(method), urlheaderbody,通常以纯文本方式发送
HTTP返回内容包括状态码,headerbody,通常以纯文本方式返回
header以及body间以CRLF(\r\n)分割

1、最基础的抓取网站内容

使用python编写一个网络爬虫是非常简单的,如下例所示:

1
2
3
import urllib2
content = urllib2.urlopen('http://armsword.com').read()

Read More

Linux IO复用—select poll 和 epoll

在Socket编程时,为了处理大量客户的连接请求,需要使用非阻塞I/O和端口复用,select、poll和epoll是Linux API提供的I/O复用方式。其实在*nix下的网络并发方法向来不缺,比如典型的Apache模型(Process Per Connection,简称PPC),TPC(Thread Per Connection)模型,这两种模型思想类似,就是利用了多进程、多线程概念,让进来的每一个连接去干别的事情去。但是连接多了以后,首先需要较大的内存,且进程/线程切换开销会非常大,因此这类模型能接受的最大连接数都不会太高。

Linux 2.6中加入了epoll之后(据说Windows下使用的是IOCP,但是我没使用过),在高性能服务器领域中得到广泛的应用,主要原因就是高效。在讲epoll之前,我们先总结下select、poll,因为epoll其实也就是他们的增强版本,比如select是一个系统调用,而epoll是个模块,由三个系统调用组成,内核中由文件系统实现。

Read More

记录下传输层协议TCP和UDP的一些特性

在TCP/IP中能够实现传输层功能的、具有代表性的协议是TCP和UDP。

TCP

TCP是面向连接的、可靠的流协议。流就是指不间断的数据结构,你可以把它想象成排水道中的水流。当应用程序采用TCP发送消息时,虽然可以保证发送的顺序,但还是犹如没有任何间隔的数据流发送给接收端。TCP充分地实现了数据传输时各种控制功能,可以进行丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。而这些在UDP中都没有。此外,TCP作为一种面向有连接的协议,只有在确认通信对端存在时才会发送数据,从而可以控制通信流量的浪费。根据TCP的这些机制,在IP这种无连接的网络上也能够实现高可靠性的通信。

TCP为提供可靠性传输,实行“顺序控制”或“重发控制”机制。此外还具备“流控制(流量控制)”、“拥塞控制”、提供网络利用率等众多功能。

TCP通过检验和、序列号、确认应答、重发控制、连接管理以及窗口控制等机制实现可靠性传输。

Read More