php memcache分布式的学习笔记

 更新时间:2016年11月25日 16:34  点击:1827
memcached虽然称为“分布式”缓存服务器,但服务器端并没有“分布式”功能。服务器端仅包括内存存储功能,其实现非常简单。至于memcached的分布式,则是完全由客户端程序库实现的。这种分布式是memcached的最大特点。

一台Memcache通常不能满足我们的需求,这就需要分布式部署。Memcached分布式部署方案通常会采用两种方式,一种是普通Hash分布,一种是一致性Hash分布。本篇将以PHP作为客户端,来分析两种方案。
    一、普通Hash分布:
<?php
function test($key='name'){
    $md5 = substr(md5($key), 0, 8);
    $seed = 31;
    $hash = 0;
    for($i=0; $i<8; $i++){
        $hash = $hash * $seed + ord($md5[$i]);
    }
    return $hash & 0x7FFFFFFF;
}

$memcacheList = array(
        array('host'=>'192.168.1.2', 'port'=>6379),
        array('host'=>'192.168.1.3', 'port'=>6379),
        array('host'=>'192.168.1.4', 'port'=>6379),
        array('host'=>'192.168.1.5', 'port'=>6379),
);
$key = 'username';
$value = 'lane';
//根据KEY获取hash
$hash = $this->test($key);
$count = count($memcacheList);
$memcache = $memcacheList[$hash % $count];
$mc = new Memcached($memcache);
$mc->set($key, $value);
?>

    代码很简单,一个Hash函数,根据所需要的key,将他md5后取前8位,然后经过Hash算法返回一个整数。将这个整数对服务器总数求模。得到的就是服务器列表的编号。这种方式的缺点是服务器数量改变后,同一个key不同hash,将取不到值了。

    二、一致性Hash分布
    一致性Hash尽管也会造成数据的丢失,但是损失是最小的。
    将2的32次方-1想象成一个圆环,服务器列表在上面排列。根据key通过hash算法求得在圆环上的位置,那么所需要的服务器的位置在key的位置前面最近的一个(顺时针)。
<?php
class FlexiHash{
    //服务器列表
    private $serverList = array();
    //是否排序
    private $isSort = false;

    /**
     * Description: Hash函数,将传入的key以整数形式返回
     * @param string $key
     * @return int
     */
    private function myHash($key){
        $md5 = substr(md5($key), 0, 8);
        $seed = 31;
        $hash = 0;
        for($i=0; $i<8; $i++){
            $hash = $hash * $seed + ord($md5[$i]);
        }
        return $hash & 0x7FFFFFFF;
    }

    /**
     * Description: 添加新服务器
     * @param $server
     */
    public function addServer($server){
        $hash = $this->myHash($server);
        if(!isset($this->serverList[$hash])){
            $this->serverList[$hash] = $server;
        }
        $this->isSort = false;
        return true;
    }

    /**
     * Description: 删除指定服务器
     * @param $server
     * @return bool
     */
    public function removeServer($server){
        $hash = $this->myHash($server);
        if(isset($this->serverList[$hash])){
            unset($this->serverList[$hash]);
        }
        $this->isSort = false;
        return true;
    }

    /**
     * Description: 根据要操作的KEY返回一个操作的服务器信息
     * @param $key
     * @return mixed
     */
    public function lookup($key){
        //将指定的KEYhash出一个整数
        $hash = $this->myHash($key);
        if($this->isSort !== true){
            krsort($this->serverList);
            $this->isSort = false;
        }
        foreach($this->serverList as $key=>$server){
            if($key <= $hash){
                return $server;
            }
        }
        return array_pop($this->serverList);
    }
}
//使用方法
$mc = new FlexiHash();
$mc->addServer('192.168.1.2');
$mc->addServer('192.168.1.3');
$mc->addServer('192.168.1.4');
$mc->addServer('192.168.1.5');

echo 'KEY=key1时,操作的服务器为:'.$mc->lookup('key1').'<br>';
echo 'KEY=key1时,操作的服务器为:'.$mc->lookup('key2').'<br>';
echo 'KEY=key1时,操作的服务器为:'.$mc->lookup('key3').'<br>';
echo 'KEY=key1时,操作的服务器为:'.$mc->lookup('key4').'<br>';
echo 'KEY=key1时,操作的服务器为:'.$mc->lookup('key5').'<br>';
?>

存储过程是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数来调用执行它。

最近使用PHP数据库访问最新的一种技术 POD,不封装,代码也写得很少。 下面我将贴出我的代码。

代码部分:

<?php
 $dsn = "mysql:host=localhost;dbname=mysqldatabasedemo";
 $db = new PDO($dsn,'root','123456@#',array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET
   NAMES'GBK';"));
  $someInParameter1='hellow';
  $stmt = $db->prepare("CALL outputProcudure(:addName,@outASD)");
  $stmt->bindParam(':addName', $someInParameter1);
   if($stmt->execute())
   {
      $rs=$db->query('select @outASD')->fetchAll();
      $dataArray=$rs[0];
      echo("<script type='text/javascript'> alert('"+$dataArray[0]+"');</script>");
   }
   else
   {
    echo("<script type='text/javascript'> alert('插入失败');</script>");
   }
?>



mysql存储过程:




PHP_PDO 调用mysql 带返回参数的存储过程

    DROP PROCEDURE IF EXISTS pro_test;  
      
    create procedure pro_test(in val VARCHAR(50) ,out rtn int)  
    begin  
    declare err INT default 0;  
    -- 如果出现异常,会自动处理并rollback  
    declare exit handler for  sqlexception ROLLBACK ;
-- 启动事务  
start transaction;
insert into test_user values(NULL,1,'啊是大三的');  
-- set err = @@IDENTITY; -- =   获取上一次插入的自增ID;  
set err =last_insert_id(); -- 获取上一次插入的自增ID  
insert into test_user VALUES(NULL,val,err);  
  
-- 运行没有异常,提交事务  
commit;  
-- 设置返回值为1  
set rtn=1;  
end;
$name = '成都市';  
          
        $stmt = $db->prepare("CALL pro_test(?,@sp_result);");  
        $stmt->bindParam(1, $name);  
        $stmt->execute ();  
        $outputArray = $db->query("select @sp_result")->fetch(PDO::FETCH_ASSOC);
<span style="font-family: Arial, Helvetica, sans-serif;">               </span><span style="font-family: Arial, Helvetica, sans-serif;">print_r($outputArray["@sp_result"]);</span>


mysql中like模糊查询效率低我相信各位是知道的了,小编40w数据使用like非常的慢了,后来直接使用了分表才解决这个问题了,下面我们来看找出mysql中like模糊查询效率低的sql语句
相比update和insert,一般查询应该是数据库中操作最频繁的。而在有些应用场景需要用到like模糊查询,那么对于大数据,查询的时候就要注意了。

 

现在来分析一下为什么like语句查询的效率会很低,测试数据共4000000条,如下图:

 

总共的条数

 

第一步:不使用索引
下图可以看出,不使用索引的时候普通查询与like查询的耗时相当,like略长,这也是必然的,因为它要进行额外的算法。

 

like不使用索引

 

第二步:使用索引

 

如下图,使用索引后,普通查询的耗时基本算是秒查,非常快;而like查询还是耗时一秒多。
 

 

like使用索引的效果

 

第三步:分析原因

 

如下图,用explain分析一下,此时我们立刻明白了,普通查询用到了索引,但是like语句没有用到索引。

 

like用不到索引

 

所以,照成mysql中like查询效率低下的原因是:在有些情况下,like查询使用不到索引,会扫描全表。

 

最后,补充一下,like语句有时候也是可以用到索引的,如下图,如果我们查询的时候写成“like 'dd_'或者like 'dd%'”,这样是可以用到索引的,此时的查询速度也会相对的快一点。虽然快了一点,但是还是比普通查询耗时要多很多。

 

like可以使用到索引

 

因此,当表的数据量比较大的时候,尽量还是不要用like语句了。如果想做模糊搜索,建议用搜索引擎,比如solr,这样会比like强大n倍。
连接redis数据库与mysql连接也是差不多了,我们下面整理了一些关于连接redis并且一些操作例子,具体的操作例子如下所示.


对于大型网站来说,redis是非常受欢迎的,运用redis缓存之后,网站瞬间可以提速n倍。那么php如何连接redis呢,下面是一个入门的范例代码。

<?php
$redis = new Redis(); //创建一个对象
$redis->connect('127.0.0.1',6379); //连接redis
$redis->select(0); //选择数据库(默认16个数据库,0-15,这个值可以在配置文件修改。)
$redis->set('a1', 'www.daixiaorui.com'); //往redis写入一条记录
echo $redis->get('a1'); //从redis中读取一条记录
?>

Redis的PHP字符串实例

<?php
   //Connecting to Redis server on localhost
   $redis = new Redis();
   $redis->connect('127.0.0.1', 6379);
   echo "Connection to server sucessfully";
   //set the data in redis string
   $redis->set("tutorial-name", "Redis tutorial");
   // Get the stored data and print it
   echo "Stored string in redis:: " + jedis.get("tutorial-name");
?>

当执行程序时,会产生下面的结果:


Connection to server sucessfully
Stored string in redis:: Redis tutorial

Redis的PHP列表示例

<?php
   //Connecting to Redis server on localhost
   $redis = new Redis();
   $redis->connect('127.0.0.1', 6379);
   echo "Connection to server sucessfully";
   //store data in redis list
   $redis->lpush("tutorial-list", "Redis");
   $redis->lpush("tutorial-list", "Mongodb");
   $redis->lpush("tutorial-list", "Mysql");
   // Get the stored data and print it
   $arList = $redis->lrange("tutorial-list", 0 ,5);
   echo "Stored string in redis:: "
   print_r($arList);
?>

当执行程序时,会产生下面的结果:


Connection to server sucessfully
Stored string in redis::
Redis
Mongodb
Mysql

Redis的PHP键例

 
<?php
   //Connecting to Redis server on localhost
   $redis = new Redis();
   $redis->connect('127.0.0.1', 6379);
   echo "Connection to server sucessfully";
   // Get the stored keys and print it
   $arList = $redis->keys("*");
   echo "Stored keys in redis:: "
   print_r($arList);
?>

当执行程序时,会产生下面的结果:


Connection to server sucessfully
Stored string in redis::
tutorial-name
tutorial-list

就是这么简单,感觉有点像连接mysql数据库一样。运行以上代码前,请确认您的电脑是否已安装并启动redis服务;请确认php已安装redis扩展,这个具体请在phpinfo查看。如果没有安装,去官网下一个对应php版本的扩展即可。

预处理语句对于防止 MySQL 注入了,我们在mssql中通常会通过存储过程来进行过滤了,但在mysql与php中并不能样处理 ,下面我们一起来看看PHP MySQL 预处理语句学习笔记,希望例子能够对各位有帮助。


预处理语句及绑定参数

 

预处理语句用于执行多个相同的 SQL 语句,并且执行效率更高。

 

预处理语句的工作原理如下:

 

预处理:创建 SQL 语句模板并发送到数据库。预留的值使用参数 "?" 标记 。例如:INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)

数据库解析,编译,对SQL语句模板执行查询优化,并存储结果不输出
执行:最后,将应用绑定的值传递给参数("?" 标记),数据库执行语句。应用可以多次执行语句,如果参数的值不一样。

相比于直接执行SQL语句,预处理语句有两个主要优点:

预处理语句大大减少了分析时间,只做了一次查询(虽然语句多次执行)
绑定参数减少了服务器带宽,你只需要发送查询的参数,而不是整个语句
预处理语句针对SQL注入是非常有用的,因为 参数值发送后使用不同的协议,保证了数据的合法性。
MySQLi 预处理语句

以下实例在 MySQLi 中使用了预处理语句,并绑定了相应的参数:

实例 (MySQLi 使用预处理语句)

<?php

$servername = "localhost";

$username = "username";

$password = "password";

$dbname = "myDB";

// 创建连接

$conn = new mysqli($servername, $username, $password, $dbname);

// 检测连接

if ($conn->connect_error) {

    die("Connection failed: " . $conn->connect_error);

}

// prepare and bind

$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)");

$stmt->bind_param("sss", $firstname, $lastname, $email);

// 设置参数并执行

$firstname = "John";

$lastname = "Doe";

$email = "john@example.com";

$stmt->execute();

$firstname = "Mary";

$lastname = "Moe";

$email = "mary@example.com";

$stmt->execute();

$firstname = "Julie";

$lastname = "Dooley";

$email = "julie@example.com";

$stmt->execute();

echo "New records created successfully";

$stmt->close();

$conn->close();

?>
解析以下实例的每行代码:
"INSERT INTO MyGuests (firstname, lastname, email) VALUES(?, ?, ?)"

在 SQL 语句中,我们使用了问号 (?),在此我们可以将问号替换为整型,字符串,双精度浮点型和布尔值。
接下来,让我们来看下 bind_param() 函数:
$stmt->bind_param("sss", $firstname, $lastname, $email);
该函数绑定了 SQL 的参数,且告诉数据库参数的值。 "sss" 参数列处理其余参数的数据类型。s 字符告诉数据库该参数为字符串。


参数有以下四种类型:

 

i - integer(整型)
d - double(双精度浮点型)
s - string(字符串)
b - BLOB(布尔值)
每个参数都需要指定类型。
通过告诉数据库参数的数据类型,可以降低 SQL 注入的风险。
Note 注意: 如果你想插入其他数据(用户输入),对数据的验证是非常重要的。
PDO 中的预处理语句

以下实例我们在 PDO 中使用了预处理语句并绑定参数:


实例 (PDO 使用预处理语句)

<?php

$servername = "localhost";

$username = "username";

$password = "password";

$dbname = "myDBPDO";

try {

    $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);

    // 设置 PDO 错误模式为异常

    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // 预处理 SQL 并绑定参数

    $stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) 

    VALUES (:firstname, :lastname, :email)");

    $stmt->bindParam(':firstname', $firstname);

    $stmt->bindParam(':lastname', $lastname);

    $stmt->bindParam(':email', $email);

    // 插入行

    $firstname = "John";

    $lastname = "Doe";

    $email = "john@example.com";

    $stmt->execute();

    // 插入其他行

    $firstname = "Mary";

    $lastname = "Moe";

    $email = "mary@example.com";

    $stmt->execute();

    // 插入其他行

    $firstname = "Julie";

    $lastname = "Dooley";

    $email = "julie@example.com";

    $stmt->execute();

    echo "New records created successfully";

    }

catch(PDOException $e)

    {

    echo $sql . "<br>" . $e->getMessage();

    }

$conn = null;

?>

[!--infotagslink--]

相关文章

  • PHP分布式框架如何使用Memcache同步SESSION教程

    本教程主要讲解PHP项目如何用实现memcache分布式,配置使用memcache存储session数据,以及memcache的SESSION数据如何同步。 至于Memcache的安装配置,我们就不讲了,以前...2016-11-25
  • php上传图片学习笔记与心得

    我们在php中上传文件就必须使用#_FILE变量了,这个自动全局变量 $_FILES 从 PHP 4.1.0 版本开始被支持。在这之前,从 4.0.0 版本开始,PHP 支持 $HTTP_POST_FILES 数组。这...2016-11-25
  • Smarty模板学习笔记之Smarty简介

    1、简介Smarty是一个使用PHP写出来的模板PHP模板引擎,是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲,目...2014-05-31
  • PHP+memcache实现消息队列案例分享

    memche消息队列的原理就是在key上做文章,用以做一个连续的数字加上前缀记录序列化以后消息或者日志。然后通过定时程序将内容落地到文件或者数据库。php实现消息队列的用处比如在做发送邮件时发送大量邮件很费时间的问...2014-05-31
  • php Observer观察者模式之学习笔记

    当我们在星际中开地图和几家电脑作战的时候,电脑的几个玩家相当于结盟,一旦我们出兵进攻某一家电脑,其余的电脑会出兵救援。 那么如何让各家电脑知道自己的盟友被攻击了...2016-11-25
  • PHP 日期函数 学习笔记介绍

    举一个简单的date例子 我将使用echo命令把内容输出到我们的客户端(浏览器)。我将使用下面的代码做为基础代码。 代码如下 复制代码 <!DOCTY...2016-11-25
  • Android学习笔记之多界面切换实例

    一篇Android学习笔记之多界面切换实例,希望对各位朋友有所帮助。 用过VB 、 VC#的朋友都知道,在VB或VC#里要进行窗口(界面)切换很容易 例如在VB、C#里: 有 Fom1、...2016-09-20
  • php中的变量引用传值学习笔记

    引用:意思是将原始对象在内存中的地址传递给目标对象,就相当于原始对象和目标对象指向的是同一个内存地址。此时,如果对目标对象或者原始对象进行修改,内存中的数据也会改...2016-11-25
  • PHP中的cURL请求及示例学习笔记

    cURL是php中一个很强大的功能,可以模仿各种用户请求,如模仿用户登录,发送php cookie等等操作,下面我来整理一些相关的方法与各位同学看看 备注:使用curl_init函数,必须...2016-11-25
  • Windows下Memcache的安装方法

    很多phper不知道如何在Windows下搭建Memcache的开发调试环境,最近个人也在研究Memcache,记录下自己安装搭建的过程。 ...2016-01-27
  • 在Mac OS的PHP环境下安装配置MemCache的全过程解析

    这篇文章主要介绍了在Mac OS的PHP环境下安装配置MemCache的全过程解析,MemCache是一套分布式的高速缓存系统,需要的朋友可以参考下...2016-02-18
  • 那些年,我还在学习C# 学习笔记

    那些年学了ASP.NET后,才开始学习C#,说来也怪,怎么学了ASP.NET才来学习C#,其实没有什么的...2020-06-25
  • YII2 WIDGET的学习笔记

    CWidget是所有Widget的基类。CWidget是自包含组件,可以看出是MVC的简略版,CWidget相比Controller,既没有actions,也没有filters widget,英文意思为小工具,小挂件,在程序...2016-11-25
  • metasploit调用nexpose扫描学习笔记

    Metasploit是一个免费的、可下载的框架,通过它可以很容易地获取、开发并对计算机软件漏洞实施攻击。它本身附带数百个已知软件漏洞的专业级漏洞攻击工具 nexpose安...2016-11-25
  • php学习笔记之PHP扩展开发教程

    PHP扩展开发不是所有开发者都会操作的一个东西,下面我来演示一个关于PHP扩展开发实现过程,各位同学有需要可进入参考。 我们先假设需要这样一个扩展,提供一个叫tao_s...2016-11-25
  • php memcache和php memcached比较以及问题

    php memcache和php memcached是php的memcache分布式的高速缓存系统的两个客户端,php memcache是老客户端,php memcached是功能更加完善的新的代替php memcached的。...2016-11-25
  • Yii2学习笔记之汉化yii设置表单的描述

    小编推荐的这篇文章介绍了Yii2学习笔记之汉化yii设置表单的描述,非常实用,有兴趣的同学快来看看吧。 一:汉化框架&#8195;&#8195;框架汉化在这里设置,如果不生效,前台后...2017-07-06
  • php Builder建造器模式学习笔记

    星际里面有不少的任务关,也可以自己编辑地图,画面上有各种地形,建筑和部队,存在一个问题,初始化画面的流程很乱。待解决的问题:完成初始化画面的工作,同时尽量减少各种绘制...2016-11-25
  • php中session学习笔记

    Session指的就是用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间。从上述的定义中我们可以看到,Session实际上是一个...2016-11-25
  • php memcache和memcached模块安装应用

    memcache的官方主页:php教程.net/package/memcache">http://pecl.php.net/package/memcache memcached的官方主页:http://pecl.php.net/package/memcached 以下是我安装...2016-11-25