喜悦国际村 » 喜悦原创 » 关于数据的散列存储

页: [1]
fly5122008-7-16 01:00 PM
关于数据的散列存储

先申明提点,咱们是穷人,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]]

fly5122008-7-16 01:06 PM
现在来实现数据的存储

由于程序要通过某些关键数据来散列数据,所以在写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]]

fly5122008-7-16 01:35 PM
关于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]

fly5122008-7-16 01:42 PM
以上的程序系统有一个通病,就是没办法实现24*7的服务,比如某台DB当掉了,

那么就有一部分的用户无法得到服务。

只要对 config::modTable和DB数组进行一点改造,然后结合mysql主从库就能实现

phphp2008-7-16 04:48 PM
config::charMod比分布式的mm有啥好处?

fly5122008-7-16 11:14 PM
和他当然是不能比的,只能是通过php程序来实现数据分布存储,

然后在查询时,将请求代理到不同的mysql服务器,这样可以响应更高的并发请求

xieaotian2008-7-17 12:02 AM
我的思路还没有你的高级呢,你的思路已经不错了。

jiayuwoa2008-7-19 07:36 AM
看不懂

zlst2008-7-21 03:35 PM
版主,整 个连接代码打个包好不好呀?
require_once(R_P.'/include/'.$type.'/'.$class.'.php');
的代码是什么

dhgdmw2008-7-22 03:02 AM
真不错 ,收藏了

fly5122008-7-22 03:46 AM
[quote]原帖由 [i]zlst[/i] 于 2008-7-21 11:35 PM 发表
版主,整 个连接代码打个包好不好呀?
require_once(R_P.'/include/'.$type.'/'.$class.'.php');
的代码是什么 [/quote]

那是mysql操作类,自己可以写的,和上面讲的没有太大关系

zlst2008-7-22 07:59 AM
不会用呀,例子给一个好不好

zlst2008-7-22 03:29 PM
求config::modTable()的实现

zlst2008-7-23 07:17 AM
怎么决定insert/update/select/delete哪一个分表?如果分表不在同一个数据库里又如何?

fly5122008-7-24 03:24 AM
对于楼上的提问?我是在不知道该怎么说

因为在上面都写了

zlst2008-7-24 01:53 PM
config::modTable($table, $param);
modTable晒一下啦大侠

yangyunlifess2008-8-4 06:25 AM
顶一下 好东西


查看完整版本: 关于数据的散列存储


Powered by Discuz! Archiver 6.1.0  © 2001-2006 Comsenz Inc.
Processed in 0.007113 second(s), 2 queries