cgi在2000年或更早的时候用得比较多, 以前web服务器一般只处理静态的请求,web服务器会根据这次请求的内容,然后会fork一个新进程来运行外部c程序 (或perl脚本…), 这个进程会把处理完的数据返回给web服务器,最后web服务器把内容发送给用户,刚才fork的进程也随之退出。 如果下次用户还请求改动态脚本,那么web服务器又再次fork一个新进程,周而复始的进行。

后来出现了一种更高级的方式是, web服务器可以内置perl解释器或php解释器。 也就是说这些解释器做成模块的方式,web服务器会在启动的时候就启动这些解释器。 当有新的动态请求进来时,web服务器就是自己解析这些perl或php脚本,省得重新fork一个进程,效率提高了。

fastcgi的方式是,web服务器收到一个请求时,他不会重新fork一个进程(因为这个进程在web服务器启动时就开启了,而且不会退 出),web服务器直接把内容传递给这个进程(进程间通信,但fastcgi使用了别的方式,tcp方式通信),这个进程收到请求后进行处理,把结果返回 给web服务器,最后自己接着等待下一个请求的到来,而不是退出。 
fastcgi跟cgi的区别是:
                  在web服务器方面                                                         在对数据进行处理的进程方面
cgi
         fork一个新的进程进行处理                                           读取参数,处理数据,然后就结束生命期
fastcgi   用tcp方式跟远程机子上的进程或本地进程建立连接       要开启tcp端口,进入循环,等待数据的到来,处理数据

举个例子: 服务端现在有个10万个字单词, 客户每次会发来一个字符串,问以这个字符串为前缀的单词有多少个。 那么可以写一个程序,这个程序会建一棵trie树,然后每次用户请求过来时可以直接到这个trie去查找。 但是如果以cgi的方式的话,这次请求结束后这课trie也就没了,等下次再启动该进程时,又要新建一棵trie树,这样的效率就太低下了。   而用fastcgi的方式的话,这课trie树在进程启动时建立,以后就可以直接在trie树上查询指定的前缀了。

 

3、select, poll和epoll的区别
select

select最早于1983年出现在4.2bsd中,它通过一个select()系统调用来监视多个文件描述符的数组,当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位,使得进程可以获得这些文件描述符从而进行后续的读写操作。

select目前几乎在所有的平台上支持,其良好跨平台支持也是它的一个优点,事实上从现在看来,这也是它所剩不多的优点之一。

select的一个缺点在于单个进程能够监视的文件描述符的数量存在最大限制,在linux上一般为1024,不过可以通过修改宏定义甚至重新编译内核的方式提升这一限制。

另外,select()所维护的存储大量文件描述符的,随着文件描述符数量的增大,其复制的开销也线性增长。同时,由于网络响应时间的延迟 使得大量tcp连接处于非活跃状态,但调用select()会对所有socket进行一次线性扫描,所以这也浪费了一定的开销。

poll

poll在1986年诞生于system v release 3,它和select在本质上没有多大差别,但是poll没有最大文件描述符数量的限制。 

poll和select同样存在一个缺点就是,包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪,它的开销随着文件描述符数量的增加而线性增大。 

另外,select()和poll()将就绪的文件描述符告诉进程后,如果进程没有对其进行io操作,那么下次调用select()和poll() 的时候将再次报告这些文件描述符,所以它们一般不会丢失就绪的消息,这种方式称为水平触发(level triggered)。

epoll

直到linux2.6才出现了由内核直接支持的实现方法,那就是epoll,它几乎具备了之前所说的一切优点,被公认为linux2.6下性能最好的多路i/o就绪通知方法。

epoll可以同时支持水平触发和边缘触发(edge triggered,只告诉进程哪些文件描述符刚刚变为就绪状态,它只说一遍,如果我们没有采取行动,那么它将不会再次告知,这种方式称为边缘触发),理论上边缘触发的性能要更高一些,但是代码实现相当复杂。

epoll同样只告知那些就绪的文件描述符,而且当我们调用epoll_wait()获得就绪文件描述符时,返回的不是实际的描述符,而是一个代表 就绪描述符数量的值,你只需要去epoll指定的一个数组中依次取得相应数量的文件描述符即可,这里也使用了内存映射(mmap)技术,这样便彻底省掉了 这些文件描述符在系统调用时复制的开销。

另一个本质的改进在于epoll采用基于事件的就绪通知方式。在select/poll中,进程只有在调用一定的方法后,内核才对所有监视的文件描 述符进行扫描,而epoll事先通过epoll_ctl()来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用类似callback的回调 机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便得到通知。

 

4、memcache和redis区别

  1. redis中,并不是所有的数据都一直存储在内存中的,这是和memcached相比一个最大的区别。
  2. redis在很多方面具备数据库的特征,或者说就是一个数据库系统,而memcached只是简单的k/v缓存。
  3. 他们的扩展都需要做集群;实现方式:master-slave、hash。
  4. 在100k以上的数据中,memcached性能要高于redis。
  5. 如果要说内存使用效率,使用简单的key-value存储的话,memcached的内存利用率更高,而如果redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于memcached。当然,这和你的应用场景和数据特性有关。
  6. 如果你对数据持久化和数据同步有所要求,那么推荐你选择redis,因为这两个特性memcached都不具备。即使你只是希望在升级或者重启系统后缓存数据不会丢失,选择redis也是明智的。
  7. redis和memcache在写入性能上面差别不大,读取性能上面尤其是批量读取性能上面memcache更强