memcached 集群c++客户端

memcached 是一个高性能内存缓存,在作为缓存,不需要持久化的场性能稳定,由于现在服务器内存较大,很多应用场景单台memcached就能满足业务需求,普通的官方c API

就能满足需求。

而大型的应用数据量很大,也应该考虑单点故障,集群化可以分散压力,单点故障影响较小。集群的管理通常有两种方式:1.普通hash 2.一致性hash

1.普通hash实现相对简单,效率更高,但是不能动态扩展,这种能满足业务数据不是经常扩展比较固定的场景,单点故障影响不大,这种长期其实很多。通常的mysql + memcached 架构很适合这种方式

2.一致性哈希的优点就是可以动态扩展,适合业务数据持续增长的场景,实现相对复杂,通常需要代理服务器管理

下面是自己实现的基于hash的memcached 集群c++客户端代码,经过线上测试,性能和稳定性没有太大的问题。

/************************************************
function: c++ mcached api
author:liuyi
date:2012.12.31
version:3.0
modify:2014.10.15
*************************************************/

#ifndef MULI_MEMCACHE_H
#define MULI_MEMCACHE_H

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <time.h>
#include "libmemcached/memcached.h"
using namespace std;

typedef unsigned int(*hash_fun)(const char*);
unsigned int rs_hash(const char *str)
{
	unsigned int b = 378551;
	unsigned int a = 63689;
	unsigned int hash = 0;
	while (*str)
	{
		hash = hash * a + (*str++);
		a *= b;
	}
	return (hash & 0x7FFFFFFF);
}

struct memcache_info
{
	string host;
	int port;
};

class single_memcached
{
	public:
		single_memcached()
		{
			servers = NULL;
			memc = NULL;
			rc = MEMCACHED_SUCCESS;
			result_buff = NULL;
		}

		virtual ~single_memcached()
		{
			memcached_free(memc);
			delete []result_buff;
		}

		enum {MAX_VALUE_LEN = 1024*1024};

		bool init(const char*host, const int& port)
		{
			result_buff = new char[MAX_VALUE_LEN];
			if(result_buff == NULL)
				return false;

			memc = memcached_create(NULL);
			servers = memcached_server_list_append(NULL, host, port, &rc);
			if(servers == NULL)
				return false;
			rc = memcached_server_push(memc, servers);
			if(rc == MEMCACHED_SUCCESS)
			{
				memcached_server_free(servers);
				return true;
			}
			else
			{
				return false;
			}
		}

		//插入或者覆盖原有数据 expiration为有效时间,默认0为一直有效
		bool set(const char* key, const char* value, time_t expiration = 0)
		{
			rc = memcached_set(memc, key, strlen(key), value, strlen(value), expiration, 0);
			return rc == MEMCACHED_SUCCESS;
		}

		//删除数据 expiration为有效时间,默认0为立即生效
		bool delete_k_v(const char* key, time_t expiration = 0)
		{
			rc = memcached_delete(memc, key, strlen(key), expiration);
			return  rc == MEMCACHED_SUCCESS;
		}

		char *get(const char* key)
		{
			size_t value_len = 0;
			uint32_t flag = 0;
			char *ret = memcached_get(memc, key, strlen(key), &value_len, &flag, &rc);
			if(ret == NULL)
			{
				return NULL;
			}
			memset(result_buff, 0, MAX_VALUE_LEN);
			if(value_len < MAX_VALUE_LEN)
			{
				memcpy(result_buff, ret, value_len);
				free(ret);
			}

			return rc == MEMCACHED_SUCCESS && value_len < MAX_VALUE_LEN  ? result_buff : NULL;
		}

	private:
		memcached_server_st *servers;
		memcached_st *memc;
		memcached_return rc;
		char *result_buff;
};

class mulit_memcached
{
	public:
		mulit_memcached()
		{
			memcache_servers.clear();
			memcache_servers_id.clear();
		}

		virtual ~mulit_memcached()
		{
		}

		bool init(const vector<memcache_info>& memcache_info_vec, hash_fun hash = rs_hash)
		{
			m_hash_fun = hash;
			memcache_servers.resize(memcache_info_vec.size());
			for(size_t i = 0; i < memcache_info_vec.size(); i++)
			{
				char value[1024] = {0};
				snprintf(value, 1023, "%s#%d", memcache_info_vec[i].host.c_str(), memcache_info_vec[i].port);
				memcache_servers_id.insert(pair<unsigned int, string>(i, value));
				if(!memcache_servers[i].init(memcache_info_vec[i].host.c_str(), memcache_info_vec[i].port))
				{
					return false;
				}
			}
			return true;
		}

		bool set(const char* key, const char* value, time_t expiration = 0)
		{
			unsigned int index = m_hash_fun(key) % memcache_servers.size();
			return memcache_servers[index].set(key, value, expiration);
		}

		bool delete_k_v(const char* key, time_t expiration = 0)
		{
			unsigned int index = m_hash_fun(key) % memcache_servers.size();
			return memcache_servers[index].delete_k_v(key, expiration);
		}

		char *get(const char* key)
		{
			unsigned int index = m_hash_fun(key) % memcache_servers.size();
			return memcache_servers[index].get(key);
		}

		string get_memcache_info(const char* key)
		{
			unsigned int index = m_hash_fun(key) % memcache_servers.size();
			return memcache_servers_id[index];
		}

	private:
		vector<single_memcached> memcache_servers;
		map<unsigned int, string> memcache_servers_id;
		hash_fun m_hash_fun;
};

#endif

//test

#include <iostream>
#include <string>
#include "memcache_api.h"
using namespace std;

unsigned int user_define_hash(const char *str)
{
	unsigned int b = 378551;
	unsigned int a = 63689;
	unsigned int hash = 0;
	while (*str)
	{
		hash = hash * a + (*str++);
		a *= b;
	}
	hash += 1;
	hash -= 1;
	return (hash & 0x7FFFFFFF);
}

int main(int argc, char *argv[])
{
	single_memcached mc;
	if(!mc.init("10.101.88.244", 11212))
	{
		cout<<"mc init error"<<endl;
	}

	char key[1024] = {0};
	char value[1024] = {"1"};
	if(!mc.set(key, value))
	{
	//	cout<<"set error"<<endl;
	}
	for(int i = 0; i < 1000; i++)
	{
		sprintf(key, "%d", i);
		if(!mc.set(key, key)){cout<<"error"<<endl;}
		if(mc.get(key))cout<<mc.get(key)<<endl;
		mc.delete_k_v(key);
	}

	memcache_info host_port;
	host_port.host = "10.101.88.244";
	host_port.port = 11211;
	vector<memcache_info> servers;
	servers.push_back(host_port);
	host_port.port = 11212;
	servers.push_back(host_port);
	mulit_memcached mulit_memcached_servers;
	if(!mulit_memcached_servers.init(servers))
	//if(!mulit_memcached_servers.init(servers, user_define_hash))
	{
		cout<<"init error"<<endl;
	}
	for(int i = 0; i < 1000; i++)
	{
		char k[16] = {0};
		sprintf(k, "%d", i);
		//cout<<k<<endl;
		cout<<mulit_memcached_servers.set(k, k)<<endl;;
		cout<<mulit_memcached_servers.set(k, k, 100)<<endl;;
		if(mulit_memcached_servers.get(k))cout<<mulit_memcached_servers.get(k)<<endl;
		cout<<mulit_memcached_servers.delete_k_v(k)<<endl;
		cout<<mulit_memcached_servers.get_memcache_info(key)<<endl;//user for log
	}
	return 0;
}
时间: 2024-11-08 00:53:35

memcached 集群c++客户端的相关文章

nginx+PHP+memcached+MySQL+ip-hash做memcached集群

1.nginx与memcached整合 #安装memcached支持的事务库libevent wget https://github.com/libevent/libevent/releases/download/release-2.0.22-stable/libevent-2.0.22-stable.tar.gz tar zxf libevent-2.0.22-stable.tar.gz  cd libevent-2.0.22-stable ./configure --prefix=/usr/

CAS服务器集群和客户端集群环境下的单点登录和单点注销解决方案

CAS的集群环境,包括CAS的客户应用是集群环境,以及CAS服务本身是集群环境这两种情况.在集群环境下使用CAS,要解决两个问题,一是单点退出(注销)时,CAS如何将退出请求正确转发到用户session所在的具体客户应用服务器,而不是转发到其他集群服务器上,二是解决CAS服务端集群环境下各种Ticket信息的共享. CAS集群部署 由于CAS Server是一个Web应用,因此可部署在Tomcat等容器中.直接部署CAS集群并使用负载均衡配置后,由于每次访问的CAS Server不固定,会发生通

Memcached集群架构方面的问题(转)

add by zhj: 这是一个系列中的第二篇,该系列有四篇,英文原文没找到,译文见:http://blog.csdn.net/jarfield/article/details/4336035 ,附上另外三篇链接http://blog.csdn.net/jarfield/article/details/4322953,http://blog.csdn.net/jarfield/article/details/4341819, http://blog.csdn.net/jarfield/artic

Memcached集群/分布式/高可用 及 Magent缓存代理搭建过程 详解

当网站访问量达到一定时,如何做Memcached集群,又如何高可用,是接下来要讨论的问题. 有这么一段文字来描述“Memcached集群” Memcached如何处理容错的? 不处理!:) 在memcached节点失效的情况下,集群没有必要做任何容错处理.如果发生了节点失效,应对的措施完全取决于用户.节点失效时,下面列出几种方案供您选择: * 忽略它! 在失效节点被恢复或替换之前,还有很多其他节点可以应对节点失效带来的影响. * 把失效的节点从节点列表中移除.做这个操作千万要小心!在默认情况下(

Redis 学习(三)redis服务器集群、客户端分片

下面是来自知乎大神的一段说明,个人觉得非常清晰,就收藏了. 为什么集群? 通常,为了提高网站响应速度,总是把热点数据保存在内存中而不是直接从后端数据库中读取.Redis是一个很好的Cache工具.大型网站应用,热点数据量往往巨大,几十G上百G是很正常的事儿,在这种情况下,如何正确架构Redis呢? 首先,无论我们是使用自己的物理主机,还是使用云服务主机,内存资源往往是有限制的,scale up不是一个好办法,我们需要scale out横向可伸缩扩展,这需要由多台主机协同提供服务,即分布式多个Re

Ubuntu 16.04通过Magent搭建Memcached集群(转)

一.下载Magent 官网:https://code.google.com/archive/p/memagent/downloads 离线版本:(链接: https://pan.baidu.com/s/1kU9DLI3 密码: k6qg) 二.编译安装 说明:magent由于是10年的产品,所以编译时一定会报错,但是先不要按照网上的修改来操作,应该先执行make,然后看错误来解决,因为每个系统的解决方式都不同,应该按照不同的系统来处理才是最优的解法. 前提:先安装Memcached,参考:htt

Magent搭建Memcached集群

Magent搭建Memcached集群 Memcached集群介绍 由于Memcached服务器与服务器之间没有任何通讯,并且不进行任何数据复制备份,所以当任何服务器节点出现故障时,会出现单点故障,如果需要实现HA,则需要通过另外的方式来解决. 通过Magent缓存代理,防止单点现象,缓存代理也可以做备份,通过客户端连接到缓存代理服务器,缓存代理服务器连接缓存连接服务器,缓存代理服务器可以连接多台Memcached机器可以将每台Memcached机器进行数据同步.如果其中一台缓存服务器down机

160530、memcached集群(spring集成的配置)

第一步:在linux机或windows机上安装memcached服务端(server) linux中安装memcached:centos中命令 yum -y install memcached 如果没有联网下载mencached的安装包(注意:需要安装依赖libevent) 从网上下载安装包,解压后make&&make install就完成了 第二步:项目中导入memcached客户端jar(client)有两个版本,选择2.4的 第三步:spring集成memcached(memcach

Memcached 集群的高可用(HA)架构

Memcache自身并没有实现集群功能,如果想用Memcahce实现集群需要借助第三方软件或者自己设计编程实现,这里将采用memagent代理实现,memagent又名magent,大家注意下,不要将这二者当成两种工具.至于memcache.magent的安装请参考文章  在Linux上安装Memcached服务和 magent编译安装及常见错误 整体架构 直接上图: 从图中可以看到有两个magent节点,两个memcached节点,每个magent节点又分别代理两个memcached节点,应用