页:
[1]
|
关于数据的散列存储
先申明提点,咱们是穷人,mysql的集群我可没有用过,这里的数据散列是有程序方面控制来实现的
在这里,我们先从最简单的数据散列开始。
假设你有多台mysql服务器(或者一台mysql服务器建立多个库来模拟也行),多台memcached服务器(一台开多个端口也可以)
第一步:数据散列。
由于数据是被散列在不同的mysql服务器上,所以以下的所有操作都[color=Red]不能出现连表操作[/color]
如何散列数据使得数据能够平均的分配到所有的服务器上,这个每个人可以选择不同的方法。
下面的方法是个简单的散列数据的方法
[php]
/*对数字分表的数据散列*/
private static function intMod($val, $num)
{
return $val%$num;
}
/*对字符串分表的数据散列*/
private static function charMod($val, $num)
{
$len = strlen($val);
$ascii = 0;
for($i=0; $i<$len; $i++) $ascii += ord($val[$i]);
return self::intMod($ascii, $num);
}
[/php]
以上的方法返回的是该数据在mysql服务器数组中的服务器序号
比如返回值为0,则数据会被存储到database的下表为0的服务器里
[php]
/*mysql服务器数组,memcached服务器数组*/
private static $config = array(
'database'=>array(
0=>array(
'servername'=>'localhost',// 数据库服务器名或IP地址
'dbusername'=>'root',// 数据库帐号
'dbpassword'=>'123456',// 数据库密码
'dbname'=>'sns', // 数据库名称
),
1=>array(
'servername'=>'localhost',// 数据库服务器名或IP地址
'dbusername'=>'root',// 数据库帐号
'dbpassword'=>'123456',// 数据库密码
'dbname'=>'sns_1', // 数据库名称
),
),
'memcached'=>array(
0=>array(
'servername' => '127.0.0.1',
'port' => 11211,
),
),
'table' =>array(
/* 参数1:是否分表,2:按哪个字段分,3:字段类型(int || char),4:分几张表 */
/* 如果一张表被分成100张表,而你有10个mysql数据库服务器,则每个服务器中会存储10张表数据 */
'sns_album'=>array(1,'id', 'int', 10),
'sns_album_mapping'=>array(1, 'uid', 'int', 10),
'sns_album_class'=>array(1, 'uid', 'int', 2),
'sns_album_class_mapping'=>array(1, 'classid', 'int', 10),
),
);
[/php]
[[i] 本帖最后由 fly512 于 2008-7-16 09:02 PM 编辑 [/i]] |
|
现在来实现数据的存储
由于程序要通过某些关键数据来散列数据,所以在写sql的时候有点特殊要求
下面提供了一组操作数据的方法
[php]
/*mysql 操作类*/
class db
{
private static $_db_manager = array();
private static $_db_index = 0;
private static function _get_db()
{
if(!isset(self::$_db_manager[self::$_db_index])){
$option = config::get('database');
self::$_db_manager[self::$_db_index] = base::get_object('lib', 'mysq', $option[self::$_db_index]['servername'], $option[self::$_db_index]['dbusername'], $option[self::$_db_index]['dbpassword'], $option[self::$_db_index]['dbname']);
}
return self::$_db_manager[self::$_db_index];
}
public static function set($index = 0)
{
self::$_db_index = $index;
}
public static function close()
{
if(!is_array(self::$_db_manager)) return false;
foreach(self::$_db_manager as $obj) $obj->close();
return true;
}
public static function exec($sql)
{
return self::_get_db()->exec($sql);
}
public static function get_one($sql)
{
$temp = self::get_row($sql);
return $temp === false ? false : array_shift($temp);
}
public static function get_row($sql)
{
$temp = self::_get_db()->fetch($sql);
return isset($temp[0]) ? $temp[0] : false;
}
public static function fetch($sql)
{
return self::_get_db()->fetch($sql);
}
}
[/php]
[php]
class base
{
public static function get_object($type, $class)
{
require_once(R_P.'/include/'.$type.'/'.$class.'.php');
$args_num = func_num_args();
if($args_num== 2) return new $class();
static $max_param = 5;
$args = func_get_args();
if($args_num - 2 < $max_param) for($i=$args_num; $i<$max_param+2; ++$i) $args[$i] = NULL;
return new $class($args[2], $args[3], $args[4], $args[5], $args[6]);
}
/*获取某类时间的全局自增值*/
public static function max_id($type)
{
static $table = array('global_event');
in_array($type, $table) || die('error');
db::set(0);
return db::exec("insert into {$type} () values ()");
}
/*查询sql构造*/
public static function select($field , $table, $param, $other = '')
{
$option = config::modTable($table, $param);
db::set($option[0]);
$table = $option[1];
$primary = $option[2];
$sql = array();
foreach($param as $key=>$val) $sql[] = " `$key`='$val' ";
if(is_array($field)) $field = implode(',', $field);
$sql = "select {$field} from {$table} where ". implode(' and ', $sql) . ' ' .$other ;
return db::fetch($sql);
}
/*更新sql构造*/
public static function update($table, &$param, &$where)
{
$option = config::modTable($table, $where);
db::set($option[0]);
$table = $option[1];
$primary = $option[2];
$sql = $and = '';
foreach($param as $key=>$val) $sql .= "`$key`='$val',";
$sql = substr( $sql, 0, -1);
if(is_array($where)){
foreach($where as $key=>$val) $and .= " `$key`='$val' and";
$and = ' where ' . substr($and, 0, -3);
}
$sql = "update {$table} set {$sql} {$and}";
return db::exec($sql);
}
/*删除sql构造*/
public static function delete($table, &$param)
{
$option = config::modTable($table, $param);
db::set($option[0]);
$table = $option[1];
$primary = $option[2];
$sql = array();
if(is_array($param)){
foreach($param as $key=>$val) $sql[] = " `$key`='$val' ";
$sql = "delete from {$table} where ".implode(' and ', $sql);
}else{
$sql = "delete from {$table} ";
}
return db::exec($sql);
}
/*插入sql构造*/
public static function insert($table, &$param, $type = 'insert')
{
$option = config::modTable($table, $param);
db::set($option[0]);
$table = $option[1];
$primary = $option[2];
$sql = array();
foreach( $param as $key=>$val){
$sql[0][] = $key;
$sql[1][] = $val;
}
$sql = "{$type} into {$table} (`" .implode("`,`", $sql[0]). "`) values ('" .implode("','", $sql[1]). "')";
return db::exec($sql);
}
}
[/php]
[[i] 本帖最后由 fly512 于 2008-7-16 09:13 PM 编辑 [/i]] |
|
关于memcached的数据缓存
memcached是个什么东东,搜村子里的文章就知道了 。
对数据散列缓存到不同的memcached的服务器上,其原理与database的一致
[php]
class cache
{
private static $_memcache_manage = null;
private static $_memcache_index = 0;
private static $_memcache_count = 0;
private static function _get_instance() {
if(!isset(self::$_memcache_manage[self::$_memcache_index])){
$option = config::get('memcahce');
self::$_memcache_manage[self::$_memcache_index] = new Memcache;
self::$_memcache_manage[self::$_memcache_index]->connect($option[self::$_memcache_index]['servername'], $option[self::$_memcache_index]['port']);
}
return self::$_memcache_manage[self::$_memcache_index];
}
private static function _get_key($key){
if(self::$_memcache_count == 0) self::$_memcache_count = count(config::get('memcahce'));
self::$_memcache_index = config::charMod($key, self::$_memcache_count);
return $key;
}
public static function get($key){
return self::_get_instance()->get(self::_get_key($key));
}
public static function delete($key, $timeout = 0){
return self::_get_instance()->delete(self::_get_key($key), $timeout);
}
public static function set($key, $cache){
return self::_get_instance()->set(self::_get_key($key), $cache, MEMCACHE_COMPRESSED, 1000);
}
public static function close(){
if(!is_array(self::$_memcache_manage)) return true;
foreach(self::$_memcache_manage as $val){
$val->close();
}
}
}
[/php] |
|
以上的程序系统有一个通病,就是没办法实现24*7的服务,比如某台DB当掉了,
那么就有一部分的用户无法得到服务。
只要对 config::modTable和DB数组进行一点改造,然后结合mysql主从库就能实现 |
|
| config::charMod比分布式的mm有啥好处? |
|
和他当然是不能比的,只能是通过php程序来实现数据分布存储,
然后在查询时,将请求代理到不同的mysql服务器,这样可以响应更高的并发请求 |
| xieaotian | 2008-7-17 12:02 AM |
|
| 我的思路还没有你的高级呢,你的思路已经不错了。 |
| jiayuwoa | 2008-7-19 07:36 AM |
|
| 看不懂 |
|
版主,整 个连接代码打个包好不好呀?
require_once(R_P.'/include/'.$type.'/'.$class.'.php');
的代码是什么 |
|
[quote]原帖由 [i]zlst[/i] 于 2008-7-21 11:35 PM 发表
版主,整 个连接代码打个包好不好呀?
require_once(R_P.'/include/'.$type.'/'.$class.'.php');
的代码是什么 [/quote]
那是mysql操作类,自己可以写的,和上面讲的没有太大关系 |
|
| 怎么决定insert/update/select/delete哪一个分表?如果分表不在同一个数据库里又如何? |
|
对于楼上的提问?我是在不知道该怎么说
因为在上面都写了 |
|
config::modTable($table, $param);
modTable晒一下啦大侠 |
| yangyunlifess | 2008-8-4 06:25 AM |
|
| 顶一下 好东西 |
Powered by Discuz! Archiver 6.1.0
© 2001-2006 Comsenz Inc.
Processed in 0.007113 second(s), 2 queries |