memcached简介(研究spymemcached源码前的准备)
第一次自己写博客,而且水平有限,请大家多指点。
Memcached是一个高性能的分布式内存对象缓存系统,用于动态web应用已减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态,数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap,其守护进程(daemon)是C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。
此次主要研究的是Memcached的客户端(spymemcached)的源码,所有要首先学习下memcached协议从而才能对客户端源码有个深入了解。
比较详细的Memcached协议可以参考http://blog.s135.com/book/memcached/。
此处我把我认为几点比较重要的写一下。Memcached的客户端使用TCP连接于服务器通讯(udp也可以)。服务器一直监视着一些端口譬如11211端口,客户端编写代码连接该端口进行通信。因为memcached被设计成即使开启很多连接也能够高效的工作,缓存这些连接可以消除建立连接所带来的开销,所有在编写客户端的时候不用每次连接获得数据之后就关闭连接,所以也不用考虑像数据库连接中的连接池的问题,如果每次数据库连接都不进行关闭,而且数据库连接数是有限的,那么当数据库连接数达到一定数量,那么就不能建立新的连接。
在memcached的协议中发送的数据分为两种:文本行和自由数据。文本行被用于客户端的命令和服务器端的回应。自有数据用于客户端从服务器端存放或者获取时发送的。服务器会以字节流的方式传回自有数据。文本行固定以“\r\n”结束。自由数据也是同样以“\r\n”结束,但是\r(回车符)、\n(换行符),以及任何其他8位字符,均可出现在数据中。因此,当客户端从服务器取回数据时,必须使用数据区块的长度来确定数据区块的结束位置,而不要依据数据区块末尾的“\r\n”,即使它们固定存在于此。此存可以这样理解memcached可以通过telnet192.168.228.39999这样连接memcached。然后通过getkey来获得key值为key对应的数据,而通过tcp连接传递的时候其实是字节流,通过将
getkey\r\n
END\r\n
转化为字节流传递给服务器,服务器做出反应返回
VALUE<key><flags><bytes>\r\n
<datablock>\r\n
不过此处也是对应的字节流,第一行可以认为是文本行,而第二行可以认为是自由数据。其实spymemcached通过socket建立连接,将以上的字符串转化为字节流发送给服务器,然后获得服务器返回的字节流转化为字符串,或者对应的对象。其实<datablock>就是我们想要的数据,当然前提是不出现error。
其他具体的信息可以参考http://blog.s135.com/book/memcached/。
对于客户端与服务器端必然要传递数据,传递数据就要考虑到I/O。看了接近一个月的spymemcached的源码,发现收获最大的就是I/O这块。
总结下就是,阻塞的建立建立之后,进行read,当没有数据是程序会挂起,cpu转而执行其他线程,数据为准备好,read会一直阻塞,那么该线程就无法继续往下运行。而非阻塞,有一个主线程来处理所有的IO,并负责分发,当你建议连接之后,吧你这个链接绑定到主线程下,然后,你这个线程可以继续做其他的事情,这个是通过事件驱动机制来实现,主线程会一直查看到底哪些线程准备好了,那么就执行该线程的读取或写入。java通过选择器selector来实现。当我们建立了连接之后,将连接注册到selector之后,可以进行其他操作,而主线程无限循环来查看selector选择器哪些连接准备好了读写,然后执行读写。也就是说同步程序会一直阻塞到可以进行IO操作,而非阻塞会立刻返回一个状态为,来判断是否可以进行IO。
同步和异步是针对应用程序和内核的交互而言的,同步指的是用户触发IO操作并等待或者轮询的去查看IO操作是否就绪,而异步是用户触发IO操作之后便开始自己的事情,操作系统操作io当io操作完成时,会告诉应用程序。而spymemcached就是采用的同步非阻塞的IO,我们可以查看文档写到改客户端是单线程,异步的,这个地方的异步是指操作异步而不是IO,譬如,我进行get和set操作,是互不影响的,可以再get操作的时候进行set操作,因为这些操作是放到了队列里的,我们可以在向一个memcached的服务器进行get,另外一个进行set,我是这样认为的,请知道的给个准确的解释。
介绍就这么写,之后研究源码后可以继续体会。
由于本人是个菜鸟,很多都是引用别人的地方,有什么写的不对,请及时指出,大家共同进步。