(看完这个文章,想对源码有进一步了解,可以到我的git里面看注释,或者邮件我讨论。附上地址:https://github.com/PhoneLi/beansdb)
在开始看这篇文章之前,建议花几分钟看下beansdb的结构分析。
beansdb的结构分析:http://blog.csdn.net/l402398703/article/details/19371515
简述:
1:数据存储实现。bitcask储存模型,HashTree 实现数据索引。
2:协议实现。使用memcached的代码;修改redis的AE事件异步驱动库;多worker线程, leader/follower 模式;
(leader/follower模式介绍:http://www.habadog.com/2012/01/11/leader-follower-thread-model
bitcask模型介绍:http://blog.nosqlfan.com/html/955.html)
--------------------------==============水平分割线=================------------------------------
运行流程:
1:beansdb.c的main函数启动;
2:getopt处理各参数;
3:一些资源的初始化,例如 getrlimit() , item_init(); stats_init(); conn_init();(资源参数很多,建议不要花事件耗在这里。等看完后面的函数代码,便会自然理解参数的含义。);
4:hs_open函数 {
打开数据目录(没有则创建),hstore的初始化。函数结尾调用parallelize函数;
parallelize函数:启动一些线程运行scan_thread,每个scan_thread 运行对应的bc_scan。
bc_scan:加载目录里面的 XXX.[data|hint.qlz|htree]文件。(ht_open 加载HTREE_FILE 文件,sanHintFile 加载 hintpath文件)
};
5:server_socket:socket的初始化。
6:loop_run:{
创建子线程,各线程进入worker_main函数。
worker_main里面实现了leader/follwer模式。当有conn的网络事件,调用driver_machine函数。
driver_machine:{
(c-state default is conn_listening;)
switch:
conn_listening: accept client socket ,and new std conn.
conn_read:{
try_read_network读取命令,try_read_command处理命令。
如果是set命令,process_update_command函数处理,则将状态转入conn_nread,从而接受二进制数据;
如果是get命令,process_get_command函数处理,则从beansdb中提取key对应的value,并将状态转入conn_mwrite,从而发送查询结果数据;
如果是其他的命令,例如delete,version,stats等,由于回应消息都比较简单,都是直接调用out_string,跳转到conn_write状态。
}
conn_nread:conn_nread标志着正在从客户端读取二进制数据。这种情况发生在客户端发送set命令的时候。如果全部二进制数据读取完成,则将
其存储到beansdb中,并调用 out_string将存储结果返回给客户。
conn_write. 当服务器需要发送一些简单的回应的时候(out_string函数),会将连接的状态设置为conn_write. conn_write状态的处理机制就是
首先调用add_iov来将对应的回应消息添 加到msghdr中的iov中,然后调用transmit函数将未发送的数据发送出去,最后全部数据传输完成时,将状态置为conn_read。
conn_mwrite. 这种情况一般是发生在需要向用户返回大量的二进制查询结果时。处理动作也是调用transmit将缓存的数据发送出去。
conn_closing. 对应的动作就是清除连接。
}
}
--------------------------==============水平分割线=================------------------------------
--------------------------==============水平分割线=================------------------------------
总结:
1:Key-Value 数据库(CAP理论)
分布式的,伸缩性比较好(P):性能和容量
最终一致的(C):可能出现短时间内的数据不一致
高可用的(A):部分节点出现故障不影响服务
2:典型用法
图片文件,小媒体文件(mp3); 大文本字段(通常> 1kb); profile , properties
3:网上有关beansdb源码分析的文章不多。而且那些文章对应的beansdb的版本不是最新的。
所以。如果想了解最新版本beansdb(0.6.0)的源码,可以看我的git。里面有一定数量的注释。日后有时间,我会规范整理的。
我的git项目地址:https://github.com/PhoneLi/beansdb
--------------------------==============水平分割线=================------------------------------
美图欣赏:
举例一个查找流程:
hs_get先对key做hash,决定value是在哪个bitcast。然后调用bitcast模块的bc_get
bc_get先调用htree模块的ht_get,找到对应的Item。
Item中有版本信息ver,位置信息pos。pos是bucket的id和偏移量拼成的一个uint32,于是得到了bucket和offset然后就可以读出数据了。
原文:http://blog.csdn.net/l402398703/article/details/19903733