基于memcache接口的统一存储工具类设计
刚开始处理的时候,临时想做一个统一接口的key-value数据的存储方式。然后我模拟memcached接口,写了个简单的k-v数据存储的工具类。
临时想到,暂且记下。
1.接口类/**
*存储工具抽象接口类
*
*/
abstractclassStoreTool
{
abstractpublicfunctionset($key,$val);
abstractpublicfunctionget($key);
abstractpublicfunctionreplace($key,$val);
abstractpublicfunctiondelete($key);
abstractpublicfunctionflush();
abstractpublicfunctionincrement($key,$val=1);
abstractpublicfunctionadd($key,$val);
}
复制代码
2.memcached和mysql处理(mysql用的heapengine)/**
*mysqlheapengin存储工具类
*
*/
classDbStoreToolextendsStoreTool
{
staticprivate$_instance;
private$_dbh;
private$_tablename='mmouc_memory_kv';
staticpublicfunctiongetInstance($config){
if(self::$_instance==null){
self::$_instance=newself($config);
}
returnself::$_instance;
}
privatefunction__construct($config){
$conn=$config['persistency']?mysql_pconnect($config['host'].':'.$config['port'],$config['user'],$config['password'])
:mysql_connect($config['host'].':'.$config['port'],$config['user'],$config['password']);
if($conn){
if($config['charset'])mysql_query("SETNAMES'".$config['charset']."'",$conn);
if(!empty($config['database'])){
$dbselect=mysql_select_db($config['database'],$conn);
if(!$dbselect){
mysql_close($conn);
$conn=$dbselect;
}
}
$this->_dbh=$conn;
$this->_tablename=$config['tablename'];
}
}
/**
*Storedataattheserver
*storesanitemvarwithkeyonthememcachedserver
*
*@paramunknown_type$key
*@paramunknown_type$val
*@returnunknown
*/
publicfunctionset($key,$val){
$res=$this->update($key,$val);
if(0===$res){
return$this->add($key,$val);
}
returntrue;
}
/**
*Replacevalueoftheexistingitem
*shouldbeusedtoreplacevalueofexistingitemwithkey.
*Incaseifitemwithsuchkeydoesn'texists,ThisfunctionreturnsFALSE
*
*@paramunknown_type$key
*@paramunknown_type$val
*@returnunknown
*/
publicfunctionreplace($key,$val){
$res=$this->update($key,$val);
if(0===$res){
returnfalse;
}
returntrue;
}
publicfunctionget($key){
if(is_array($key)){
$in_keys="'".implode("','",$key)."'";
$sql="
SELECT`k`,`v`FROM`".$this->_tablename."`
WHERE`k`IN({$in_keys})
";
$res=mysql_query($sql,$this->_dbh);
if(empty($res)){
returnMMO_STORE_OP_ERROR;
}
$_arr_res=array();
while($row=mysql_fetch_assoc($res)){
$row['v']=unserialize($row['v']);
$_arr_res[$row['k']]=$row;
}
$out=array();
foreach($keyas$_k){
$out[]=$_arr_res[$_k]['v'];
}
return$out;
}elseif(is_string($key)){
$sql="
SELECT`v`FROM`".$this->_tablename."`
WHERE`k`='{$key}'
";
$res=mysql_query($sql,$this->_dbh);
if(empty($res)){
return-1;
}
$row=mysql_fetch_assoc($res);
if(empty($row)){
returnMMO_STORE_ITEM_NOT_EXIST;
}
returnunserialize($row['v']);
}else{
returnfalse;
}
}
publicfunctiondelete($key){
$sql="
DELETEFROM`".$this->_tablename."`
WHERE`k`='$key'
";
$res=mysql_query($sql,$this->_dbh);
if(!$res){
returnMMO_STORE_OP_ERROR;
}
returnmysql_affected_rows($this->_dbh);
}
publicfunctionflush(){
$sql="TRUNCATETABLE`".$this->_tablename."`";
$res=mysql_query($sql,$this->_dbh);
return$res?true:false;
}
/**
*
*TODO:
*修改这里的并发访问问题
*
*@paramunknown_type$key
*@paramunknown_type$val
*@returnunknown
*/
publicfunctionincrement($key,$val=1){
$_db_val=$this->get($key);
if(MMO_STORE_ITEM_NOT_EXIST==$_db_val){
//不存在
returnfalse;
}
$val=intval($_db_val)+intval($val);
$this->update($key,$val);
return$val;
}
/**
*Addanitemtotheserver
*
*storesvariablevarwithkeyonlyifsuchkeydoesn'texistattheserveryet
*
*@paramunknown_type$key
*@paramunknown_type$val
*@returnunknown
*/
publicfunctionadd($key,$val){
if(!$this->_isExist($key)){
$val=serialize($val);
$time=time();
$sql="
INSERTINTO`".$this->_tablename."`
SET`k`='{$key}',
`v`='{$val}',
`t`='{$time}'
";
$res=mysql_query($sql,$this->_dbh);
return$res?true:MMO_STORE_OP_ERROR;
}else{
returnfalse;
}
}
privatefunction_isExist($key,$val=''){
$sql="
SELECTCOUNT(`k`)as'num'
FROM`".$this->_tablename."`
WHERE`k`='{$key}'
";
!empty($val)&&$sql.=",`v`='".serialize($val)."'";
$res=mysql_query($sql,$this->_dbh);
if(empty($res)){
return-1;
}
$row=mysql_fetch_assoc($res);
return$row['num']?true:false;
}
privatefunctionupdate($key,$val){
$val=serialize($val);
$time=time();
$sql="
UPDATE`".$this->_tablename."`
SET`v`='{$val}',
`t`='{$time}'
WHERE`k`='$key'
";
$res=mysql_query($sql,$this->_dbh);
if(!$res){
returnMMO_STORE_OP_ERROR;
}
returnmysql_affected_rows($this->_dbh);
}
}
classFileStoreTool
{
}
classMemcacheStoreToolextendsStoreTool
{
staticprivate$_instance;
private$_memcacheHandler;
staticpublicfunctiongetInstance($config){
if(self::$_instance==null){
self::$_instance=newself($config);
}
returnself::$_instance;
}
privatefunction__construct($config){
$this->_memServers=$config;
$this->_initMemcacheObj();
}
publicfunctionset($key,$val){
return$this->_memcacheHandler->set($key,$val);
}
publicfunctionget($key){
return$this->_memcacheHandler->get($key);
}
publicfunctionreplace($key,$val){
return$this->_memcacheHandler->replace($key,$val);
}
publicfunctiondelete($key){
return$this->_memcacheHandler->delete($key);
}
publicfunctionflush(){
return$this->_memcacheHandler->flush();
}
publicfunctionincrement($key,$val=1){
return$this->_memcacheHandler->increment($key,$val);
}
publicfunctionadd($key,$val){
return$this->_memcacheHandler->add($key,$val);
}
/**
*检查保存Session数据的路径是否存在
*
*@returnbool成功返回true
*/
privatefunction_initMemcacheObj(){
if(!class_exists('Memcache')||!function_exists('memcache_connect')){
die('Failed:Memcacheextensionnotinstall,pleasefromhttp://pecl.php.netdownloadandinstall');
}
if($this->_memcacheHandler&&is_object($this->_memcacheHandler)){
returntrue;
}
$this->_memcacheHandler=newMemcache;
if(!empty($this->_memServers)){
foreach($this->_memServersas$_host=>$_port){
$this->_memcacheHandler->addServer($_host,$_port);
}
}
returntrue;
}
}
复制代码
3.mysql和file相关
mysql记录方式,对应表建表语句如下:
CREATETABLEIFNOTEXISTS`mmouc_memory_kv`(
`k`varchar(40)NOTNULLCOMMENT'键名',
`v`varchar(2048)NOTNULLCOMMENT'键值的serialize值',
`t`int(10)NOTNULLDEFAULT'0'COMMENT'更新时间',
PRIMARYKEY(`k`)
)ENGINE=MEMORYDEFAULTCHARSET=utf8COMMENT='代替memcache数据记录表';
对于file,暂未处理,以后补上。
4.todo:
a.对于memcached数据的遍历方式策略,需要做一个完备而统一接口的策略算法处理类,可以在多种分级存储模式,和存储策略间任意切换;
b. file存储工具类补上