• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • memcached深度分析(7)

    發表于:2015-07-10來源:uml.org.cn作者:火龍果軟件點擊數: 標簽:數據庫
    這個擴展是使用php的stream直接連接memcached服務器并通過socket發送命令的。它不像libmemcache那樣完善,也不支持add_server這種分布操作,但是因為它不依賴其它

      這個擴展是使用php的stream直接連接memcached服務器并通過socket發送命令的。它不像libmemcache那樣完善,也不支持add_server這種分布操作,但是因為它不依賴其它的外界程序,兼容性要好一些,也比較穩定。至于效率,差別不是很大。

      另外,有很多的PHP class可以使用,比如MemcacheClient.inc.php,phpclasses.org上可以找到很多,一般都是對perl client API的再封裝,使用方式很像。

      BSM_Memcache

      從C client來說,APR_Memcache是一個很成熟很穩定的client程序,支持線程鎖和原子級操作,保證運行的穩定性。不過它是基于APR的(APR將在最后一節介紹),沒有libmemcache的應用范圍廣,目前也沒有很多基于它開發的程序,現有的多是一些Apache Module,因為它不能脫離APR環境運行。但是APR倒是可以脫離Apache單獨安裝的,在APR網站上可以下載APR和APR-util,不需要有Apache,可以直接安裝,而且它是跨平臺的。

      BSM_Memcache是我在BS.Magic項目中開發的一個基于APR_Memcache的PHP擴展,說起來有點拗口,至少它把APR扯進了PHP擴展中。這個程序很簡單,也沒做太多的功能,只是一種形式的嘗試,它支持服務器分組。

      和mcache擴展支持多服務器分布存儲不同,BSM_Memcache支持多組服務器,每一組內的服務器還是按照hash方式來分布保存數據,但是兩個組中保存的數據是一樣的,也就是實現了熱備,它不會因為一臺服務器發生單點故障導致數據無法獲取,除非所有的服務器組都損壞(例如機房停電)。當然實現這個功能的代價就是性能上的犧牲,在每次添加刪除數據的時候都要掃描所有的組,在get數據的時候會隨機選擇一組服務器開始輪詢,一直到找到數據為止,正常情況下一次就可以獲取得到。

      BSM_Memcache只支持這幾個函數:

    zend_function_entry bsm_memcache_functions[] =
    {
        PHP_FE(mc_get,          NULL)
        PHP_FE(mc_set,          NULL)
        PHP_FE(mc_del,          NULL)
        PHP_FE(mc_add_group,    NULL)
        PHP_FE(mc_add_server,   NULL)
        PHP_FE(mc_shutdown,     NULL)
        {NULL, NULL, NULL}
    };
    mc_add_group函數返回一個整形(其實應該是一個object,我偷懶了~_~)作為組ID,
    mc_add_server的時候要提供兩個參數,一個是組ID,一個是服務器地址(ADDR : PORT)。 
    /**
    * Add a server group
    */
    PHP_FUNCTION(mc_add_group)
    {
        apr_int32_t group_id;
        apr_status_t rv;
     
        if (0 != ZEND_NUM_ARGS())
        {
            WRONG_PARAM_COUNT;
            RETURN_NULL();
        }
     
        group_id = free_group_id();
        if (-1 == group_id)
        {
            RETURN_FALSE;
        }
     
        apr_memcache_t *mc;
        rv = apr_memcache_create(p, MAX_G_SERVER, 0, &mc);
     
        add_group(group_id, mc);
     
        RETURN_DOUBLE(group_id);
    }
    /**
    * Add a server into group
    */
    PHP_FUNCTION(mc_add_server)
    {
        apr_status_t rv;
        apr_int32_t group_id;
        double g;
        char *srv_str;
        int srv_str_l;
        if (2 != ZEND_NUM_ARGS())
        {
            WRONG_PARAM_COUNT;
        }
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ds", &g, &srv_str, &srv_str_l) == FAILURE)
        {
            RETURN_FALSE;
        }
        group_id = (apr_int32_t) g;
     
        if (-1 == is_validate_group(group_id))
        {
            RETURN_FALSE;
        }
        char *host, *scope;
        apr_port_t port;
        rv = apr_parse_addr_port(&host, &scope, &port, srv_str, p);
        if (APR_SUCCESS == rv)
        {
            // Create this server object
            apr_memcache_server_t *st;
            rv = apr_memcache_server_create(p, host, port, 0, 64, 1024, 600, &st);
            if (APR_SUCCESS == rv)
            {
                if (NULL == mc_groups[group_id])
                {
                    RETURN_FALSE;
                }
     
                // Add server
                rv = apr_memcache_add_server(mc_groups[group_id], st);
     
                if (APR_SUCCESS == rv)
                {
                    RETURN_TRUE;
                }
            }
        }
     
        RETURN_FALSE;
    }
    在set和del數據的時候,要循環所有的組: 
    /**
    * Store item into all groups
    */
    PHP_FUNCTION(mc_set)
    {
        char *key, *value;
        int key_l, value_l;
        double ttl = 0;
        double set_ct = 0;
        if (2 != ZEND_NUM_ARGS())
        {
            WRONG_PARAM_COUNT;
        }
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|d", &key, &key_l, &value, &value_l, ttl) == FAILURE)
        {
            RETURN_FALSE;
        }
        // Write data into every object
        apr_int32_t i = 0;
        if (ttl < 0)
        {
            ttl = 0;
        }
        apr_status_t rv;
     
        for (i = 0; i < MAX_GROUP; i++)
        {
            if (0 == is_validate_group(i))
            {
                // Write it!
                rv = apr_memcache_add(mc_groups[i], key, value, value_l, (apr_uint32_t) ttl, 0);
                if (APR_SUCCESS == rv)
                {
                    set_ct++;
                }
            }
        }
     
        RETURN_DOUBLE(set_ct);
    }
    在mc_get中,首先要隨機選擇一個組,然后從這個組開始輪詢:
    
    /**
    * Fetch a item from a random group
    */
    PHP_FUNCTION(mc_get)
    {               
        char *key, *value = NULL;
        int key_l;
        apr_size_t value_l;
     
        if (1 != ZEND_NUM_ARGS())
        {
            WRONG_PARAM_COUNT;
        }
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_l) == FAILURE)
        {
            RETURN_MULL();
        }
        // I will try ...
        // Random read
        apr_int32_t curr_group_id = random_group();
        apr_int32_t i = 0;
        apr_int32_t try = 0;
        apr_uint32_t flag;
        apr_memcache_t *oper;
        apr_status_t rv;
     
        for (i = 0; i < MAX_GROUP; i++)
        {
            try = i + curr_group_id;
            try = try % MAX_GROUP;
            if (0 == is_validate_group(try))
            {
                // Get a value
                oper = mc_groups[try];
                rv = apr_memcache_getp(mc_groups[try], p, (const char *) key, &value, &value_l, 0);
                if (APR_SUCCESS == rv)
    
                {
                    RETURN_STRING(value, 1);
                }
            }
        }
     
        RETURN_FALSE;
    }
    /**
    * Random group id
    * For mc_get()
    */
    apr_int32_t random_group()
    {
        struct timeval tv;
        struct timezone tz;
        int usec;
     
        gettimeofday(&tv, &tz);
     
        usec = tv.tv_usec;
     
        int curr = usec % count_group();
     
        return (apr_int32_t) curr;
    }

    原文轉自:http://www.uml.org.cn/sjjm/201411134.asp

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>