Memcached】
[PHP扩展]
php_memcache 客户端:
连接超时:bool Memcache::connect ( string $host [, int $port [, int $timeout ]] )
在get和set的时候,都没有明确的超时设置参数。
libmemcached 客户端:在php接口没有明显的超时参数。
说明:所以说,在PHP中访问Memcached是存在很多问题的,需要自己hack部分操作,或者是参考网上补丁。
[C&C++访问Memcached]
客户端:libmemcached 客户端
说明:memcache超时配置可以配置小点,比如5,10个毫秒已经够用了,超过这个时间还不如从数据库查询。
下面是一个连接和读取set数据的超时的C++示例:
- //创建连接超时连接到Memcached)
- memcached_st* MemCacheProxy::_create_handle()
- {
- memcached_st * mmc = NULL;
- memcached_return_t prc;
- if (_mpool != NULL) { // get from pool
- mmc = memcached_pool_pop(_mpool, false, &prc);
- if (mmc == NULL) {
- __LOG_WARNING__("MemCacheProxy", "get handle from pool error [%d]", (int)prc);
- }
- return mmc;
- }
- memcached_st* handle = memcached_create(NULL);
- if (handle == NULL){
- __LOG_WARNING__("MemCacheProxy", "create_handle error");
- return NULL;
- }
- // 设置连接/读取超时
- memcached_behavior_set(handle, MEMCACHED_BEHAVIOR_HASH, MEMCACHED_HASH_DEFAULT);
- memcached_behavior_set(handle, MEMCACHED_BEHAVIOR_NO_BLOCK, _noblock); // 参数MEMCACHED_BEHAVIOR_NO_BLOCK为1使超时配置生效,不设置超时会不生效,关键时候会悲剧的,容易引起雪崩
- memcached_behavior_set(handle, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, _connect_timeout); //连接超时
- memcached_behavior_set(handle, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, _read_timeout); //读超时
- memcached_behavior_set(handle, MEMCACHED_BEHAVIOR_SND_TIMEOUT, _send_timeout); //写超时
- memcached_behavior_set(handle, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, _poll_timeout);
- // 设置一致hash
- // memcached_behavior_set_distribution(handle, MEMCACHED_DISTRIBUTION_CONSISTENT);
- memcached_behavior_set(handle, MEMCACHED_BEHAVIOR_DISTRIBUTION, MEMCACHED_DISTRIBUTION_CONSISTENT);
- memcached_return rc;
- for (uint i = 0; i < _server_count; i++){
- rc = memcached_server_add(handle, _ips[i], _ports[i]);
- if (MEMCACHED_SUCCESS != rc) {
- __LOG_WARNING__("MemCacheProxy", "add server [%s:%d] failed.", _ips[i], _ports[i]);
- }
- }
- _mpool = memcached_pool_create(handle, _min_connect, _max_connect);
- if (_mpool == NULL){
- __LOG_WARNING__("MemCacheProxy", "create_pool error");
- return NULL;
- }
- mmc = memcached_pool_pop(_mpool, false, &prc);
- if (mmc == NULL) {
- __LOG_WARNING__("MyMemCacheProxy", "get handle from pool error [%d]", (int)prc);
- }
- //__LOG_DEBUG__("MemCacheProxy", "get handle [%p]", handle);
- return mmc;
- }
- //设置一个key超时set一个数据到memcached)
- bool MemCacheProxy::_add(memcached_st* handle, unsigned int* key, const char* value, int len, unsigned int timeout)
- {
- memcached_return rc;
- char tmp[1024];
- snprintf(tmp, sizeof (tmp), "%u#%u", key[0], key[1]);
- //有个timeout值
- rc = memcached_set(handle, tmp, strlen(tmp), (char*)value, len, timeout, 0);
- if (MEMCACHED_SUCCESS != rc){
- return false;
- }
- return true;
- }
- //Memcache读取数据超时 (没有设置)
- libmemcahed 源码中接口定义:
- LIBMEMCACHED_API char *memcached_get(memcached_st *ptr,const char *key, size_t key_length,size_t *value_length,uint32_t *flags,memcached_return_t *error);
- LIBMEMCACHED_API memcached_return_t memcached_mget(memcached_st *ptr,const char * const *keys,const size_t *key_length,size_t number_of_keys);
从接口中可以看出在读取数据的时候,是没有超时设置的。
延伸阅读:
http://hi.baidu.com/chinauser/item/b30af90b23335dde73e67608
http://libmemcached.org/libMemcached.html
如何实现超时】
程序中需要有超时这种功能,比如你单独访问一个后端Socket模块,Socket模块不属于我们上面描述的任何一种的时候,它的协议也是私有的,那么这个时候可能需要自己去实现一些超时处理策略,这个时候就需要一些处理代码了。
[PHP中超时实现]
一、初级:最简单的超时实现 秒级超时)
思路很简单:链接一个后端,然后设置为非阻塞模式,如果没有连接上就一直循环,判断当前时间和超时时间之间的差异。
php socket 中实现原始的超时:(每次循环都当前时间去减,性能会很差,cpu占用会较高)
- <?
- $host = "127.0.0.1";
- $port = "80";
- $timeout = 15; //timeout in seconds
- $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
- or die("Unable to create socket\n");
- socket_set_nonblock($socket) //务必设置为阻塞模式
- or die("Unable to set nonblock on socket\n");
- $time = time();
- //循环的时候每次都减去相应值
- while (!@socket_connect($socket, $host, $port)) //如果没有连接上就一直死循环
- {
- $err = socket_last_error($socket);
- if ($err == 115 || $err == 114)
- {
- if ((time() - $time) >= $timeout) //每次都需要去判断一下是否超时了
- {
- socket_close($socket);
- die("Connection timed out.\n");
- }
- sleep(1);
- continue;
- }
- die(socket_strerror($err) . "\n");
- }
- socket_set_block($this->socket) //还原阻塞模式
- or die("Unable to set block on socket\n");
- ?>
PHP之友评论