前言:
本人在网络上并未找到magent的实际应用的例子,都是一些测试,本人想通过java调用代理magent来解决单点故障的问题,但是没有相关的文档API介绍。其实本人在学习memcached与magent之后,发现网络上,很多人并没有把magent理解对,并不知道它是什么一个角色,只知道是个memcached代理,然后就互相抄袭拷贝对方的文章,有的压根都没有自己亲手测试过。就算自己真正动手测试过magent的,但是并没有把它运用到实际的项目中,起码在本人看来,暂时java还没法调用magent,没有相关的客户端API。
其实对于magent,大家可以把它理解成是memcached客户端的一个扩展,它同样有java client、spymemcached、xmemcached它们的功能,支持ketama一致性hash算法,多了一个memcached备份功能而已。只是暂时我们只可以用telnet进入magent启动的进程服务set、get值的,并没有方法来直接通过代码调用magent服务set、get值,这也是我为什么认为magent没有实际应用的原因。就拿java来说,在实际应用中,我们是通过memcached客户端,来实现memcached的功能。而magent服务无法用java程序来调。
很多人都理解成了,我只要在memcached服务器上配置好magent,客户端还是采用如memcached-client-for-java来调用,当set、get值的时候,magent会自动分配并自动把值保存到备份服务器上,其实错了,既然你还是采用的memcached-client-for-java,那么就是运用的memcached-client-for-java里面的一致性hash算法了,而不是采用的magent里面的一致性hash算法了。这样做,其实还是撇开了magent。
这也是:http://www.oschina.net/question/858822_77565 中提出:
但是测试结果告诉,当A或者B,或者AB都当掉之后,取值为null。也就是说,magent代理服务并没有将值set到备份服务上。
的答案
就如一个公司的创始人(客户端)一开始有很多任务(key value)要分配(set、get)给各员工(memcached服务器)做,后来请来了一个CEO(magent),想让他来代理分配 (set、get) 工作,解决员工离职(单点故障)问题。所以正常情况下,应该是,创始人(客户端)把所有的任务(key value)直接交给CEO(magent)就行了,而不是创始人(客户端)还亲自再分配工作给员工(memcached服务器),应该直接让CEO(magent)自己去分配工作,解决员工离职(单点故障)。而现在的问题是 创始人(客户端)无法联系上(调用) CEO(magent)。
虽然感觉magent在实际项目中并无法应用,不过下面,我还是会附上magent的测试例子。其实个人觉得,在解决单点故障的问题上,可以自己采用本地备份的方法解决
以上纯属个人的理解,技术有限,如有错误,还望大家指出纠正,互相学习
-------------------------------------------------------------------------------------------------------------------------------------
memcached不提供集群功能,因为集群的要素是负载均衡和单点恢复;
memcached在server端之间是不会进行通讯的,目前比较流行的有下面第几种替代的解决方案,虽不是很完美,但是能满足一些基本需求。
1、通过客户端进行hash算法
存到不同的mamcached server上
该方法是在客户端存值之前先对key进行hash,把算出的hash对应的不同的memcached server上,这样保证了系统中的数据是存放到不同的mamcached server上,分散了在单台机器上的风险,提高了性能,缺点是单一台机器down后,它上面的数据将会丢失,没法恢复,不能动态增加机器,动态增加机器后,本地key对应server会发生改变,以前的老数据将不能取到,只能系统全部重启
当前的memcached java client就提供了该功能,代码如下
String[] serverlist = {"10.10.9.116:11211","10.10.9.116:11212"}; //定义了两台cache机器
SockIOPool pool = SockIOPool.getInstance();
pool.setServers(serverlist);
Integer weights[]=new Integer{1,3};//可以根据每台机器的性能设置不同的权重
pool.setWeights(weights);
pool.setInitConn(initConn);
pool.setMinConn(minConn);
pool.setMaxConn(maxConn);
pool.setMaintSleep(mainSleep);
pool.setNagle(false);
pool.setFailover( true );
pool.initialize();
instance = this;
2、现在通用的使用一致hash算法
,可以最大限度避免第一条中的缺点,可以动态的增加或减少机器而对现有的其他机器上的数据保持不变,只会影响小部分的数据的存取。
目前 java client、spymemcached、xmemcached都支持一致hash,同时还采用了虚拟节点的一致性hash算法,使memcached尽量的负载均衡,可以参考:http://blog.csdn.net/fdipzone/article/details/7170045
下面是memcached java client的一段代码,需要设置的几个关键属性:
pool.setNagle(true);//这是开启一个nagle 算法。改算法避免网络中充塞小封包,提高网络的利用率 ;
pool.setHashingAlg(SockIOPool.CONSISTENT_HASH);//设置为一致性hash算法,在memcached集群时使用
pool.setFailover( true ); //集群用 设置池的故障转移的标志 当一个memcached服务器失效的时候客户端默认会 failover另一个服务去.如果失效的服务器恢复运行,客户端会返回到原来连接的服务器.一般不要使用该功能
pool.setAliveCheck(true);//表示在使用Socket以前是否先检查Socket状态
3、使用memagent
上面1、2都是针对客户端在访问时候进行key的hash算法,而3的方法是基于在memcached服务端安装代理进行分发,它可以进行数据的备份,当某台机器down后会自动从备份机器取对应的数据有如下特点:
A、和每个memcache server保持多个长连接,效果是减少memcache server保持的连接数量及创建销毁连的开销。不过,memcache本身就支持大并发连接,这个功能也就没什么特别的说道。
B、支持memcache的binary协议命令,实现请求的转发。
C、和memcache一样,基于libevent的事件驱动来处理IO。
D、支持ketama 的一致性hash算法。
E、支持memcache backup集群,当memcache集群有机器挂了,memagent会将get请求转向memcache backup集群。这个功能对于cache的稳定性要求高的场景下会有用武之地。
magent是一款开源的Memcached代理服务器软件,其项目网址为:
http://code.google.com/p/memagent/
优点:系统自动备份,当一台机器down后自动切换到备份机器
------------------------------------------------------------------------------------------------------------------------------------
测试环境:
四台机器:192.168.1.105、192.168.1.151、192.168.1.152、192.168.1.153
192.168.1.105为主机,151、152、153为在105上安装的虚拟机
四台机器上均安装了memcached与magent
1.151、152、153三台机器上,分别启动两个memcached进程,端口均为11211、11212
2.现以105机器为代理机器和备份机器,即在105的机器上启动一个备份的memcached服务,端口为11213,同时再启动一个magent代理进程服务,端口为10000,做主magent服务。
3.另外在151机器上再启动一个magent服务,作为备份的magent服务,万一105机器宕机,则可以启动备份的magent服务,实际配属配置需根据实际应用环境来定,我这边只是测试一下该集群的工作机制与逻辑。
在151机器上启动两个memcached进程:
memcached -m 1 -u root -d -l 192.168.1.151 -p 11211
memcached -m 1 -u root -d -l 192.168.1.151 -p 11212
在152机器上启动两个memcached进程:
memcached -m 1 -u root -d -l 192.168.1.152 -p 11211
memcached -m 1 -u root -d -l 192.168.1.152 -p 11212
在153机器上启动两个memcached进程:
memcached -m 1 -u root -d -l 192.168.1.153 -p 11211
memcached -m 1 -u root -d -l 192.168.1.153 -p 11212
在105机器上启动一个memcached进程:备份用
memcached -m 1 -u root -d -l 192.168.1.105 -p 11213
在105机器上启动一个magent进程:
magent -u root -n 51200 -l 192.168.1.105 -p 10000 -s 192.168.1.151:11211 -s 192.168.1.151:11212 -s 192.168.1.152:11211 -s 192.168.1.152:11212 -s 192.168.1.153:11211 -s 192.168.1.153:11212 -b 192.168.1.105:11213
在151机器上启动一个magent进程:备份用
magent -u root -n 51200 -l 192.168.1.151 -p 10000 -s 192.168.1.151:11211 -s 192.168.1.151:11212 -s 192.168.1.152:11211 -s 192.168.1.152:11212 -s 192.168.1.153:11211 -s 192.168.1.153:11212 -b 192.168.1.105:11213
在105机器上:
[root@localhost ~]# memcached -m 1 -u root -d -l 192.168.1.105 -p 11213
[root@localhost ~]# magent -u root -n 51200 -l 192.168.1.105 -p 10000 -s 192.168.1.151:11211 -s 192.168.1.151:11212 -s 192.168.1.152:11211 -s 192.168.1.152:11212 -s 192.168.1.153:11211 -
插件系统应该具备一下功能:
插件探测
插件注册
插件调用
插件注销
<?php
final class Plugin{
private $plugins = null;
private $directory = 'plugins';
private $path = null;
public function __construct(){
$this->path = $this->directory.'/';
}
public function autoload(){
$interfaces = scandir($this->directory);
unset($interfaces[0]);
unset($interfaces[1]);
foreach($interfaces as $interface)
{
//load all of the plugins
$file = $this->path . $interface;
if (@file_exists($file))
{
include_once($file);
$class = basename($interface, ".php");
if (class_exists($class))
{
$this->$class = new $class($this);
$vars = get_class_vars($class);
$entity['name'] = $vars['name'];
$entity['description'] = $vars['description'];
$entity['author'] = $vars['author'];
$entity['class'] = $class;
$entity['methods'] = get_class_methods($class);
$this->plugins[$class] = $entity;
}
}
}
}
public function load($plugin){
$file = $this->path . $plugin . '.php';
if (@file_exists($file))
{
include_once($file);
$class = $plugin;
if (class_exists($class))
{
$this->$class = new $class($this);
$vars = get_class_vars($class);
$entity['name'] = $vars['name'];
$entity['description'] = $vars['description'];
$entity['author'] = $vars['author'];
$entity['class'] = $class;
$entity['methods'] = get_class_methods($class);
$this->plugins[$class] = $entity;
}
}
}
public function show(){
print_r($this->plugins);
}
}
<?php
interface iPlugin
{
public function test();
}
<?php
final class demo implements iPlugin{
public static $author = 'Neo Chen<openunix@163.com>';
public static $name = 'Demo';
public static $description = 'Demo Simple';
public function __construct(){
}
public function test(){
echo 'Hello world!!!';
}
}
<?php
function __autoload($class_name) {
require_once('library/'.$class_name . '.php');
}
//include_once('library/Plugin.php');
$plugin = new Plugin();
echo '=============================';
$plugin->load('demo');
$plugin->demo->test();
echo '=============================';
$plugin->autoload();
$plugin->show();
已有 0 人发表留言,猛击->>这里<<-参与讨论
ITeye推荐
- —软件人才免语言低担保 赴美带薪读研!—
题目链接:http://acm.hit.edu.cn/hoj/problem/view?id=3132
本题学习计算几何基础:叉积
我们怎么去判断一个点在一条线段的左侧还是右侧呢?
这就要用到向量叉积。叉积的一个非常重要的性质是通过它的符号判断两向量相互之间的顺逆时针关系:设向量P=(x1,y1),Q=(x2,y2)
如果P*Q>0则P在Q的顺时针方向;即:x2*y1 - x1*y2>0
如果P*Q=0则P与Q共线,可能同向,与可能反向;即:x2*y1 - x1*y2=0
如果P*Q<0则P在Q的逆时针方向。即:x2*y1 - x1*y2<0
如何已知两个点坐标,求其向量是简单的
另外利用二分法实现查找:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
#define maxn 100002
typedef struct
{
int x1;
int y1;
int x2;
int y2;
} NArray;
NArray nArray[maxn];
int numArray[maxn];
int x,y,n,m;
bool cmp(int a,int b)
{
return a>b;
}
bool cmp1(NArray a,NArray b)
{
return a.x1<b.x1;
}
//true代表右边,false代表左边
bool judge(int e,int px,int py)
{
return (long long)(px - nArray[e].x2) * (long long)(nArray[e].y1 - nArray[e].y2)
> (long long)(nArray[e].x1 - nArray[e].x2) * (long long)(py - nArray[e].y2);
}
//二分
void add(int px,int py)
{
if(judge(n,px,py))
{
numArray[n+1]++;
return;
}
int a = 1;
int b = n;
while(a<b)
{
int mid = (a+b)/2;
if(!judge(mid,px,py))
{
b = mid;
}
else
{
a = mid + 1;
}
}
numArray[a]++;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int px,py;
while(scanf("%d %d %d %d",&x,&y,&n,&m)!=EOF)
{
memset(numArray,0,sizeof(numArray));
for(int i=1; i<=n; i++)
{
scanf("%d %d",&nArray[i].x1,&nArray[i].x2);
nArray[i].y1 = y;
nArray[i].y2 = 0;
}
sort(nArray+1,nArray+n+1,cmp1);
for(int i=1; i<=m; i++)
{
scanf("%d %d",&px,&py);
add(px,py);
}
sort(numArray+1,numArray+n+2,cmp);
for(int j=1; j<=4; j++)
{
printf("%d ",numArray[j]);
}
printf("%d\n",numArray[5]);
}
return 0;
}