• 2013-10-23

    SSDB 增加 zrank, zrange 命令

    Views: 33604 | 6 Comments

    Zrank/zrrank 命令是 zset 数据结构的一个特有命令, 用于求某个元素在集合中的排序名次. 对于 Redis 来说, 数据都在内存里, 而且是排序的, 所以求元素的排名(indexOf)可以很快, 但因为 SSDB 的数据主要在硬盘中, 所以, 求排序名次可不是那么简单.

    基于这个考虑, SSDB 原来并不支持 zrank 命令. 但 zrank 命令的需求还是有的, 经过考虑, 所以在 1.6.3 版本中增加了 zrank 命令.

    不过, 使用这个命令应该是在离线环境中, 而不能是在线上生产环境中, 因为 zrank 的实现是通过遍历数据(相当于全表扫描).

    另外, SSDB 还增加了 zrange/zrrange 命令, 相当于数组的 slice 操作或者 MySQL 的 limit 操作. 和 zrank 类似, zrange 也是通过表扫描来实现的, 只要 offset 越大, 速度就越慢. 所以, 在 offset 小于 200 时, 可以在线上生产环境使用, 否则最好是离线环境中使用.

    Posted by ideawu at 2013-10-23 13:05:07 Tags: , , ,
  • 2013-10-22

    C++ hash_map(unordered_map)和map性能对比

    Views: 12862 | 2 Comments

    C++ STL 的 hash_map(unordered_map) 理论上能达到 O(1) 的查找速度, 而 map 是 O(log(N)). 一般会认为, map 比 hash_map 慢, 但是, 具体慢多少呢? 和元素个数有关系吗? 有没有直观的数据?

    为此, 我写了一个简单的测试程序, 分别在 100, 1000, 10000, 10000 个元素时, 对两种 map 进行查找, 对比下耗时. 结果如下:

    items  type     timespan  timestamp
    100    map      +0.432037 1382373147.689263
    100    hash_map +0.140390 1382373147.829653
    1000   map      +0.672411 1382373197.151690
    1000   hash_map +0.152739 1382373197.304429
    10000  map      +0.928384 1382373219.558242
    10000  hash_map +0.185142 1382373219.743384
    100000 map      +1.512256 1382373371.041342
    100000 hash_map +0.373361 1382373371.414702
    

    可以看到, 在元素数量较少时(1000 以内), hash_map 的速度是 map 的 3 到 4 倍. 而元素数量达到 10000 或者更多时, hash_map 的速度是 map 的 5 倍. 这就是直观的感受.

    补充了插入速度:

    100    build_map      +0.001180 1382443114.467226
    100    build_hash_map +0.000371 1382443114.467597
    1000   build_map      +0.002165 1382443150.065571
    1000   build_hash_map +0.001629 1382443150.067200
    10000  build_map      +0.012238 1382443170.254071
    10000  build_hash_map +0.019952 1382443170.274023
    100000 build_map      +0.121713 1382443188.696912
    100000 build_hash_map +0.204433 1382443188.901345
    

    可以看到, map 的插入速度比 hash_map 快速, 可以认为是 2 倍.

    Posted by ideawu at 2013-10-22 00:38:17
  • 2013-10-17

    SSDB 的 C++ 客户端接口

    Views: 29929 | 11 Comments

    SSDB 本身是用 C++ 语言编写的, 所以天生就支持 C++ 客户端 API. SSDB 源码中自带的 leveldb-import.cpp, ssdb-dump.cpp 等程序, 也是 C++ 客户端的例子. 不过, 这些 API 依赖整个项目, 编译和链接的参数非常繁琐. 因此, 有必要开发对用户友好的 C++ API, 减少依赖, 方便开发 SSDB 的 C++ 客户端应用.

    我很高兴的通知, 接口简单, 对用户友好的 SSDB 的 C++ 客户端 API 已经有了! 并且, 有了相应的 API 文档(我相信文档对于一个软件的作用是非常重要的). 我可以用一行代码了显示这个 API 的使用是如何的简单:

    g++ -o hello-ssdb hello-ssdb.cpp libssdb.a
    

    hello-ssdb.cpp 就是一个使用了 SSDB C++ API 的客户端程序, 上面的一行命令用于编译这个程序, 生成可执行文件.

    SSDB C++ API 包括了两类方法, 一类是简单方法, 另一类是语义化的方法. 简单方法就是在一个统一的函数中传递任意命令和参数. 而语义化的方法即类型 get(), set() 这样顾名思义的方法. 因为时间的缘故, 后一种方法还没有实现.(更新: 两类方法都已实现.)

    欢迎大家使用, 如果有什么意义, 欢迎反馈!

    SSDB C++ 客户端接口文档: http://www.ideawu.com/ssdb/docs/cpp/

    Posted by ideawu at 2013-10-17 23:27:05 Tags: , ,
  • 2013-09-18

    构建C1000K的服务器(2) – 实现百万连接的comet服务器

    Views: 64736 | 39 Comments

    这是关于 C1000K 序列文章的第二篇, 在前一篇文章 构建C1000K的服务器(1) – 基础 中, 介绍了支持 C1000K 的 Linux 系统的内核参数调整和系统设置. 在本篇文章中, 将对一个真正的应用服务器做 C1000K 测试.

    Comet 服务器是一类逻辑相对简单, 需要高并发连接的服务器. Comet 在网站系统中的应用非常广泛, 可以见这篇日志的介绍: http://www.ideawu.net/blog/archives/737.html.

    HTTP 协议处理

    要开发一个支持百万并发连接的 Comet 服务器, 我选择 C/C++ 语言, 当然还有其它的选择如 Erlang, Java 等. 对于一个只支持 long-polling Comet 服务器, 首先要具备解析 HTTP 协议的能力, 我选择 libevent 来处理 HTTP 协议.

    Continue reading »

    Posted by ideawu at 2013-09-18 22:06:31 Tags: , ,
  • 2013-09-17

    让libevent HTTP服务器立即知道客户端的断开

    Views: 22552 | No Comments

    虽然 libevent HTTP 服务器可以给连接注册关闭回调, 但客户端强制断开连接时, 服务器并没有立即知道.

     evhttp_connection_set_closecb(req->evcon, on_close, NULL);
    

    原来, libevent 在收到 HTTP 请求后, 就不再监听读事件了, 所以就不能通过 read() 返回 0 来知道连接断开, 只能通过 send() 导致 SIGPIPE 才能知道.

    为了让服务器立即知道客户端的断开, 只需要重新监听 EV_READ 事件即可.

    struct bufferevent *bev = evhttp_connection_get_bufferevent(req->evcon);
    bufferevent_enable(bev, EV_READ);
    
    Posted by ideawu at 2013-09-17 13:48:33 Tags:
  • 2013-09-11

    Libevent 2 HTTP 客户端示例

    Views: 22998 | No Comments

    Libevent 的文档非常少, 而且示例也很奇缺, 在 Google 里一搜, 还真找不到一两个. 这里贴一个最简单的利用 Libevent 2 HTTP 库, 作为客户端向服务器发起请求的例子.

    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <unistd.h>
    #include <evhttp.h>
    #include <event2/event.h>
    #include <event2/http.h>
    #include <event2/bufferevent.h>
    
    void http_request_done(struct evhttp_request *req, void *arg){
        char buf[1024];
        int s = evbuffer_remove(req->input_buffer, &buf, sizeof(buf) - 1);
        buf[s] = '\0';
        printf("%s", buf);
        // terminate event_base_dispatch()
        event_base_loopbreak((struct event_base *)arg);
    }
    
    int main(int argc, char **argv){
        struct event_base *base;
        struct evhttp_connection *conn;
        struct evhttp_request *req;
    
        base = event_base_new();
        conn = evhttp_connection_base_new(base, NULL, "127.0.0.1", 8080);
        req = evhttp_request_new(http_request_done, base);
    
        evhttp_add_header(req->output_headers, "Host", "localhost");
        //evhttp_add_header(req->output_headers, "Connection", "close");
    
        evhttp_make_request(conn, req, EVHTTP_REQ_GET, "/index.php?id=1");
        evhttp_connection_set_timeout(req->evcon, 600);
        event_base_dispatch(base);
    
        return 0;
    }
    
    Posted by ideawu at 2013-09-11 21:53:02 Tags:
|<<<123456789>>>| 5/12 Pages, 68 Results.