关于php php操作rediss的一个问题

& & 从某个 Redis db 导出数据到另一个 Redis db 的PHP脚本:& & 复制代码代码如下:& & $from = '127.0.0.1:6200/6';& & $to&&= '127.0.0.1:6200/8';& & $from_redis = redis_init($from);& & $to_redis&&= redis_init($to);& & $keys&= $from_redis->keys('*');& & $count = 0;& & $total = count($keys);& & foreach($keys as $key){& & if(++$count % 100 == 1){& & echo "$count/$total\n";& & }& & 0 = $from_redis->type($key);& & switch(0){& & case Redis::REDIS_STRING:& & $val = $from_redis->get($key);& & $to_redis->set($key, $val);& && & case Redis::REDIS_LIST:& & $list = $from_redis->lRange($key, 0, -1);& & foreach($list as $val){& & $to_redis->rPush($key, $val);& & }& && & case Redis::REDIS_HASH:& & $hash = $from_redis->hGetAll($key);& & $to_redis->hMSet($key, $hash);& && & case Redis::REDIS_ZSET:& & $zset = $from_redis->zRange($key, 0, -1, true);& & foreach($zset as $val=>$score){& & $to_redis->zAdd($key, $score, $val);& & }& && & }& & }& & function redis_init($conf){& & $redis = new Redis();& & preg_match('/^([^:]+)(:[0-9]+)?\\/(.+)?/', $conf, $ms);& & $host = $ms[1];& & $port = trim($ms[2], ':');& & $db = $ms[3];& & $redis->connect($host, $port);& & $redis->select($db);& & return $& & }& & 您可能感兴趣的文章:redis 队列操作的例子(php)php中使用redis队列操作实例代码在PHP中使用redisphp Session存储到Redis的方法& & QQ空间
百度搜藏更多& & Tags:PHP Redis& & 复制链接收藏本文打印本文关闭本文返回首页& & 上一篇:php使用websocket示例详解& & 下一篇:php使用GeoIP库实例& & 相关文章利用php+mysql来做一个功能强大的在线计算器解密ThinkPHP3.1.2版本之模板继承浅谈PHP与C#的值类型指向区别的详解注册页面之前先验证用户名是否存在的php代码php中3种方法删除字符串中间的空格浅析echo(),print(),print_r(),return之间的区别PHP+Ajax异步通讯实现用户名邮箱验证是否已注册( 2种方法实现)IIS6+PHP5+MySQL5+Zend Optimizer+phpMyAdmin安装配置图文教程 2使用php验证复选框有效性的示例php+js实现图片的上传、裁剪、预览、提交示例& & 文章评论& & 最 近 更 新& & 将php数组输出html表格的方法让CodeIgniter数据库缓存自动过期的处理的PHP中将网页导出为Word文档的代码关于PHP递归算法和应用方法介绍PHP中文汉字验证码PHP使用imagick读取PDF生成png缩略图的两php笔记之:有规律大文件的读取与写入的分php 购物车的例子Window 7/XP 安装Apache 2.4与PHP 5.4 的php中apc缓存使用示例& & 热 点 排 行& & php 变量定义方法简单PHP上传图片、删除图片实现代一个简单的PHP&MYSQL留言板源PHPExcel读取Excel文件的实现代码网页游戏开发入门教程二(游戏模php 购物车的例子[php] 我的微型论坛的简单教程[已PHP生成HTML静态页面实例代码php mysql数据库操作类php 网页游戏开发入门教程一(we
说明:该文章系网友上传分享,若未进行原创声明,则表明该文章系转载自互联网;若该文章内容涉嫌侵权,请及时向
上一篇:下一篇:
相关经验教程
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.004 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.001 收益
的原创经验被浏览,获得 ¥0.002 收益
的原创经验被浏览,获得 ¥0.005 收益
的原创经验被浏览,获得 ¥0.005 收益使用HAProxy、PHP、Redis和MySQL支撑10亿请求每周架构细节
High Scalability
着眼创业公司,应用程序架构主要考虑因素不只是技术,成本效益同样必不可少。因此,对于优秀的架构师,基于遗留系统、已有开发团队,以最小成本构造出可持续应用才是王道。
【编者按】在公司的发展中,保证服务器的可扩展性对于扩大企业的市场需要具有重要作用,因此,这对架构师提出了一定的要求。Octivi联合创始人兼软件架构师Antoni
Orfin将向你介绍一个非常简单的架构,使用HAProxy、PHP、Redis和MySQL就能支撑每周10亿请求。同时,你还能了解项目未来的横向扩展途径及常见的模式。
以下为译文:
在这篇文章中,我将展示一个非常简单的架构,使用HAProxy、PHP、Redis和MySQL支撑每周10亿请求。除此之外,我还将展示项目未来的横向扩展途径及常见的模式,下面我们一起看细节。
3个应用程序节点
2个MySQL+1个备份
应用程序每周处理10亿请求
峰值700请求每秒的单Symfony2实例(平均工作日约550请求每秒)
平均响应时间30毫秒
Varnish,每秒请求超过1.2万次(压力测试过程中获得)
Redis储存了1.6亿记录,数据体积大约100GB,同时它是我们的主要数据存储
MySQL储存了3亿记录,数据体积大约300GB,通常情况下它作为三级缓存层
HAProxy + Keepalived
PHP(PHP-FPM)+ Symfony2 Framework
MySQL(主从配置),使用HAProxy做负载均衡
Redis (主从配置)
大约1年前,一个朋友找到我并提出了一个苛刻的要求:它们是一个飞速发展的电子商务初创公司,而当时已经准备向国际发展。介于那个时候他们仍然是一个创业公司,初始解决方案必须符合所谓的成本效益,因此也就无法在服务器上投入更多的资金。遗留系统使用了标准的LAMP堆栈,因此他们拥有一个强力的PHP开发团队。如果必须引入新技术的话,那么这些技术必须足够简单,不会存在太多架构上的复杂性;那么,他们当下的技术团队就可以对应用进行长期的维护。
为了满足他们扩展到下一个市场的需求,架构师必须使用可扩展理念进行设计。首先,我们审视了他们的基础设施:
老系统使用了单模块化设计思路,底层是一些基于PHP的Web应用程序。这个初创公司有许多所谓的前端网站,它们大多都使用了独立的数据库,并共享了一些支撑业务逻辑的通用代码。毫不客气的说,长期维护这种应用程序绝对是一个噩梦:因为随着业务的发展,有些代码必须被重写,这样的话,修改某个网站将不可避免导致业务逻辑上的不一致,这样一来,他们不得不在所有Web应用程序上做相同的修改。
通常情况下,这该归结于项目管理问题,管理员必须对横跨多个代码库的那些代码负责。基于这个观点,整改第一步就是提取核心的业务关键功能,并将之拆分为独立的服务(这也是本文的一个重点部分),也就是所谓的面向服务架构,在整个系统内遵循“separation
of concern”原则。每个服务只负责一个业务逻辑,同时也要明确更高等级的业务功能。举个形象的例子也就是,这个系统可能是个搜索引擎、一个销售系统等。
前端网站通过REST API与服务交互,响应则基于JSON格式。为了简单起见,我们没有选择SOAP,一个开发者比较无爱的协议,因为谁都不愿意解析一堆的XML。
提取一些不会经常处理的服务,比如身份验证和会话管理。这是非常必要的一个环节,因为它们的处理等级比较高。前端网站负责这个部分,只有它们可以识别用户。这样一来我们可以保持服务的足够简单,在处理扩展和代码相关问题时都具有巨大的优势,可谓各司其职,完美无缺。
带来的好处:
独立子系统(服务)可以便捷的在不同团队中开发,开发者互不干涉,效率理所当然提升。
身份验证和会话不会通过它们来管理,因此它们造成的扩展问题不翼而飞。
业务逻辑被区分,不同的前端网站不会再存在功能冗余。
显著地提高了服务的可用性。
共生的缺点:
为系统管理员带来更大的工作量。鉴于服务都使用了独立的基础设施,这将给管理员带来更多需要关注的地方。
很难保持向后兼容。在一年的维护之后,API方法中发生了数不尽的变化。因此问题发生了,它们必将破坏向后兼容,因为每个网站的代码都可能发生变化,还可能存在许多技术人员同时修改一个网站的情况……然而,一年后,所有方法匹配的仍然是项目开始时建立的文档。
应用程序层
着眼请求工作流,第一层是应用程序。HAProxy负载均衡器、Varnish和Symfony2应用程序都在这一层。来自前端网站的请求首先会传递给HAProxy,随后负载均衡器将把他分给不同的节点。
应用程序节点配置
Xeon E5-GHz,64GB RAM,SATA
PHP 5.4.X(PHP-FPM),使用APC字节码缓存
我们购买了3个这样的服务器,N+1冗余配置的active-active模式,备份服务器同样处理请求。因为性能不是首要因素,我们为每个节点配置独立的Varnish以降低缓存hit,同时也避免了单点故障(SPOF)。在这个项目中,我们更重视可用性。因为一个前端网站服务器中使用了Apache
2,我们保留了这个堆栈。这样一来,管理员不会困扰于太多新加入的技术。
Symfony2应用程序
应用程序本身基于Symfony2建立,这是一个PHP全堆栈框架,提供了大量加速开发的组件。作为基于复杂框架的典型REST服务可能受到很多人质疑,这里为你细说:
对 PHP/Symfony 开发者友好。客户端IT团队由PHP开发者组成,添加新技术将意味必须招聘新的开发者,因为业务系统必须做长时间的维护。
清晰的项目结构。
PHP/Symfony虽然从来都不是必需品,但却是许多项目的默认选择。引入新的开发者将非常方便,因为对他们来说代码非常友好。
许多现成的组件。遵循DRY思想……没有人愿意花力气去做重复的工作,我们也不例外。我们使用了大量的Symfony2 Console
Component,这个框架非常有利于做CLI命令,以及应用程序性能分析(debug工具栏)、记录器等。
在选用Symfony2之前,我们做了大量的性能测试以保证应用程序可以支撑计划流量。我们制定了概念验证,并使用JMeter执行,我们得到了让人满意的结果——每秒700请求时响应时间可以控制在50毫秒。这些测试给了我们足够的信心,让我们坚信,即使Symfony2这样复杂的框架也可以得到理想的性能。
应用程序分析与监控
我们使用Symfony2工具来监视应用程序,在收集指定方法执行时间上表现的非常不错,特别是那些与第三方网络服务交互的操作。这样一来,我们可以发现架构中潜在的弱点,找出应用程序中最耗时的部分。
冗长的日志同样是不可缺少的一部分,我们使用PHP Monolog库把这些日志处理成优雅的log-lines,便于开发者和管理员理解。这里需要注意的是尽可能多地添加细节,越详细越好,我们使用了不同的日志等级:
Debug,可能会发生的事情。比如,请求信息在调用前会传送给一个外部Web服务;事情发生后从API调用响应。
Error,当错误发生时请求流并未被终止,比如第三方API的错误响应。
Critical,应用程序崩溃的瞬间。
因此,你可以清晰地了解Error和Critical信息。而在开发/测试环境中,Debug信息同样被记录。同时,日志被存储在不同的文件中,也就是Monolog库下的“channels”。系统中有一个主日志文件,记录了所有应用程序级错误,以及各个channel的短日志,从单独的文件中记录了来自各个channel的详细日志。
扩展平台的应用程序层并不困难,HAProxy性能并不会在短时间耗尽,唯一需要考虑的就是如何冗余以避免单点故障。因此,当下需要做的只是添加下一个应用程序节点。
我们使用Redis和MySQL存储所有的数据,MySQL更多作为三级缓存层,而Redis则是系统的主要数据存储。
在系统设计时,我们基于以下几点来选择满足计划需求的数据库:
在存储大量数据时不会影响性能,大约2.5亿记录
通常情况下多是基于特定资源的简单GET请求,没有查找及复杂的SELECT操作
在单请求时尽可能多的获得资源以降低延时
在经过一些调查后,我们决定使用Redis
大部分我们执行的操作都具有 O(1)或O(N)复杂性, N是需要检索键的数量,这意味着keyspace大小并不会影响性能。
通常情况下会使用MGET命令行同时检索100个以上的键,这样可以尽可能的避免网络延时,而不是在循环中做多重GET操作。
我们当下拥有两个Redis服务器,使用主从复制模式。这两个节点的配置相同,都是Xeon E5-.60GHz,128GB,SSD。内存限制被设置为100GB,通常情况下使用率都是100%。
在应用程序并没有耗尽单个Redis服务器的所有资源时,从节点主要作作备份使用,用以保证高有效性。如果主节点宕机,我们可以快速的将应用程序切换到从节点。在维护和服务器迁移时,复制同样被执行——转换一个服务器非常简单。
你可能会猜想当Redis资源被一直耗尽时的情景,所有的键都是持久化类型,大约占90% keyspace,剩余资源被全部被用于TTL过期缓存。当下,keyspace已经被分为两个部分:一个是TTL集(缓存),另一个则是用于持久化数据。感谢“volatile-lru”最大化内存设置的可行性,最不经常使用缓存键会被移除。如此一来,系统就可以一直保持单Redis实例同时执行两个操作——主存储和通用缓存。
使用这个模式必须一直监视“期满”键的数量:
db.redis1:6379& info keyspace
# Keyspace
db0:keys=16XXXXXXX,expires=11XXXXXX,avg_ttl=0
“期满”键数量越接近0情况越危险,这个时候管理员就需要考虑适当的分片或者是增加内存。
我们如何进行监控?这里使用Icinga check,仪表盘会显示数字是否会达到临界点,我们还使用了Redis来可视化“丢失键”的比率。
在一年后,我们已经爱上了Redis,它从未让我们失望,这一年系统从未发生任何宕机情况。
在Redis之外,我们还使用了传统RDBMS——MySQL。但是区别于他人,我们通常使用它作为三级缓存层。我们使用MySQL存储一些不会经常使用对象以降低Redis的资源使用率,因此它们被放到了硬盘上。这里没有什么可说道的地方,我们只是尽可能地让其保持简单。我们使用了两个MySQL服务器,配置是Xeon
E5-GHz,64GB RAM,SSD。两个服务器使用本地、异步的主-主复制。此外,我们使用一个单独的从节点作为备份。
MySQL的高可用性
在应用程序中,数据库永远是最难的瓶颈。当前,这里还不需要考虑横向扩展操作,我们多是纵向扩展Redis和MySQL服务器。当下这个策略还存在一定的发展空间,Redis运行在一个126GB内存的服务器上,扩展到256GB也并不困难。当然,这样的服务器也存在劣势,比如快照,又或是是简单的启动——Redis服务器启动需要很长的时间。
在纵向扩展失效后进行的必然是横向扩展,值得高兴的是,项目开始时我们就为数据准备了一个易于分片的结构:
在Redis中,我们为记录使用了4个“heavy”类型。基于数据类型,它们可以分片到4个服务器上。我们避免使用哈希分片,而是选择基于记录类型分片。这种情况下,我们仍然可以运行MGET,它始终在一种类型键上执行。
在MySQL上,结构化的表格非常易于向另一台服务器上迁移——同样基于记录类型(表格)。当然,一旦基于记录类型的分片不再奏效,我们将转移至哈希。
学到的知识
不要共享你的数据库。一旦一个前端网站期望切换会话处理到Redis,Redis缓存空间将被耗尽,同时它会拒绝应用程序保存下一个缓存键。这样一来所有的缓存将转至MySQL服务器,这将导致大量开销。
日志越详细越好。如果log-lines中没有足够的信息,快速Debug问题定位将成为难点。如此一来,你不得不等待一个又一个问题发生,直到找到根结所在。
架构中使用复杂的框架并不意味着低性能。许多人惊讶我们使用全堆栈框架来支撑如此流量应用程序,其秘诀在于更聪明的使用工具,否则即使是Node.js也可能变得很慢。选择一个提供良好开发环境的技术,没有人期望使用一堆不友好的工具,这将降低开发团队士气。
原文链接:(翻译/童阳 责编/仲浩)
免费订阅“CSDN云计算(左)和CSDN大数据(右)”微信公众号,实时掌握第一手云中消息,了解最新的大数据进展!
CSDN发布虚拟化、Docker、OpenStack、CloudStack、数据中心等相关云计算资讯, & & 分享Hadoop、Spark、NoSQL/NewSQL、HBase、Impala、内存计算、流计算、机器学习和智能算法等相关大数据观点,提供云计算和大数据技术、平台、实践和产业信息等服务。
本文为CSDN编译整理,未经允许不得转载,如需转载请联系market#csdn.net(#换成@)
CODE官方微信
扫描二维码关注
微信号:CSDN_CODE当前位置:->->文章详细内容Redis协议是从以下几个方面做的一个折中方案摘要:当一些命令以inline命令发送的时候为了使最后一个参数支持二进制安全,需要以一个特殊的格式发送。这些命令将会把最后一个参数作为「字节计数器」,然后大量的数据会被发送(这些数据可以为二进制安全,因为服务器知道有多少字节需要读取)。 看下面这个例子...
本文内容来源于&&的官方文档,对 Redis 自己的应用层进行了详细深入的讲解,由@&同学进行翻译并分享给大家。
原译文链接:
Redis协议是从以下几个方面做的一个折中方案:
机器解析要快
容易被人理解
客户端通过创建到6379端口的TCP连接来连接到一个Redis服务器。每个Redis命令或者客户端和服务器之间传输的数据都以\r\n (CRLF)结束。
Redis可以接受由不同参数组成的命令。只要接收到一个命令,这个命令就会被执行,然后一个答复会被返回给客户端。
新的统一请求协议
新的统一协议是在Redis1.2中引入的,但是在Redis2.0中成为了与Redis服务器交互的标准方式。在统一协议中所有发送到Redis服务器的参数都是二进制安全的。这是总体格式:
$CR LFCR LF
$CR LFCR LF
看下这个例子:
这是以上命令以带引号的字符串展现的样子,这样就可以看到这个请求中每个字节的准确内容:
"*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nmyvalue\r\n"
就像你一会将会看到的,这个格式还会被用在Redis回复中。这个被用于每个参数中的格式$6\r\nmydata\r\n叫做Bulk 回复。Redis实际上使用的统一请求协议会返回内容列表,叫做。它是由N个不同的Bulk 回复合在一起,并且有一个字符串前缀*\r\n其中是后面参数(Bulk回复)的数量。
Redis会以不同类型的回复对命令进行响应。可以通过服务器发送的第一个字节来判定回复的类型:
如果是单行回复,那么第一个字节是「+」
如果回复的内容是错误信息,那么第一个字节是「_」
如果回复的内容是一个整型数字,那么第一个字节是「:」
如果是bulk回复,那么第一个字节是「$」
如果是multi-bulk回复,那么第一个字节是「*」
一个状态回复(或者:单行回复)的格式是以「+」开头,以「\r\n」结束的单行字符串。举个例子:
客户端库要返回「+」后面的所有内容,这个例子里边是字符串「OK」。
错误的发送方式和状态回复很像。唯一的不同是第一个字节用「-」替代了「+」。 错误回复只有当一些奇怪的事情发生时才会被发送,例如如果你想要用错误的数据类型执行一个操作,或者这个命令不存在等等。所以客户端库应该在接收到一个错误回复的时候抛出一个异常。
这个类型的回复就是一个代表整数以CRLF结束的字符串,并且用一个字节的字符「:」作为前缀。例如「:0\r\n」,或者「:1000\r\n」都是整形回复。 像INCR或者LASTSAVE命令使用整型回复来返回一个没有特别含义的整型数字。对于INCR来说返回的是增加后的数字,对于LASTSAVE来说是一个UNIX时间等等。 像EXISTS这样的命令会返回1表示true,返回0表示false。 其他命令像SADD,SREM和SETNX在操作实际完成的时候会返回1,否则返回0。 以下命令将会返回整型回复:SETNX, DEL, EXISTS, INCR, INCRBY, DECR, DECRBY, DBSIZE, LASTSAVE, RENAMENX, MOVE, LLEN, SADD, SREM, SISMEMBER, SCARD
Bulk回复被服务器用来返回一个二进制安全的字符串。
C: GET mykey
S: $6\r\nfoobar\r\n
服务器以这种方式来发送数据:第一行是一个字节的内容「$」,之后跟着具体内容的字节数,接下来是CRLF,然后具体数据内容被发送,接下来是额外的两个字节的CRLF。服务器实际发送的序列是:
"$6\r\nfoobar\r\n"
如果请求的内容不存在,那么bulk回复将会使用特殊值-1作为数据长度,例如:
C: GET nonexistingkey
当请求对象不存在,客户端库API不要返回一个空字符串,应该是一个nil对象。举个例子一个Ruby库应该返回「nil」,一个C库应该返回NULL(或者在回复对象中设置一个特殊标记),等等。
Multi-bulk回复
像LRANGE这类的命令需要返回多个值(列表中的每个元素是一个值,LRANGE需要返回多个元素)。这通过multiple bulk write来实现,其第一行指明后面有多少个bulk write。一个multi bulk回复的第一个字节一直是*。例如:
C: LRANGE mylist 0 3
就像你看到的,multi bulk 回复和使用统一协议发送命令到Redis服务器使用的是同样的格式。 服务器发送的第一行是*4\r\n,用来指出下面将会有四个bulk回复。然后每个bulk write将会被传送。 如果指定的key不存在,那么这个key被认为拥有一个空列表,然后0会做为multi bulk的数量被发送。例如:
C: LRANGE nokey 0 1
当命令超时,它将返回值为nil的multi bulk回复。这个类型的multi bulk的数量为-1并且应该被解释为nil值。例如:
C: BLPOP key 1
当这个发生的时候,一个客户端库API应该返回一个nil对象而不是一个空列表。区分一个空的列表和一个错误条件(比如命令的超时条件)是必要的。
Multi-Bulk回复中的Nil元素
一个multi bulk 回复的单个元素可能会存在-1的长度,用来指明这个元素不存在并且不是空字符串。这个可能发生在启用了GET模式选项的SORT命令,并且指定的key不存在。包含一个空元素的multi bulk回复的例子:
第二个元素是nil。客户端库需要返回如下内容:
["foo",nil,"bar"]
多个命令和管道
一个客户端可以使用相同的连接来发送多个命令。Redis是支持管道的,所以客户端可以通过一次写操作发送多个命令,不需要读取服务器的回复才能发送下一个命令。所有的回复可以在最后读取。 通常情况下Redis服务器和客户端之间会有非常快的连接,所以客户端支持这个特性不是那么重要,但如果一个应用需要在很短的时间里发送大量的命令那么使用管道将会非常快。
发送命令的旧协议
在统一请求协议之前,Redis使用一个不同的协议来发送命令,这个协议仍然被支持因为通过telnet它很容易手写。在这个协议中存在两种命令:
inline 命令: 命令很简单,就是用空格把参数分隔开来的字符串。二进制安全是不可能的。
Bulk 命令: bulk命令和inline命令几乎是一样的,但是最后一个参数为了能够接受二进制安全的内容,所以需要以特殊的方式进行处理。
Inline命令
向Redis发送命令最简单的方法是使用inline命令。以下是一个服务器/客户端之间使用inline命令进行交互的例子(服务器以S:作为开始,客户端以C:作为开始)
以下是另一个例子,一个返回整数的inline命令:
C: EXISTS somekey
由于「somekey」不存在,所以服务器返回「:0」。 注意EXISTS命令只带有一个参数。多个参数以空格进行分隔。
当一些命令以inline命令发送的时候为了使最后一个参数支持二进制安全,需要以一个特殊的格式发送。这些命令将会把最后一个参数作为「字节计数器」,然后大量的数据会被发送(这些数据可以为二进制安全,因为服务器知道有多少字节需要读取)。 看下面这个例子:
C: SET mykey 6
这个命令的最后一个参数是「6」。这个指明了后面数据,字符串「foobar」的字节数。注意即使这些数据被额外的二个字节大小的CRLF所截断。所有bulk命令的准确格式是:把最后一个参数替换成后面数据的字节数,接下来是数据本身和CRLF。为了能够让程序员更加清晰的理解,这是上面例子中客户端发送的字符串:
"SET mykey 6\r\nfoobar\r\n"
Redis有一个内部的列表,记录了什么命令是inline,什么命令是bulk,所以你需要参考这个来发送命令。强烈推荐使用新的统一请求协议来替代旧的协议。
小困惑我想想学到了好文章赶紧学标签: ,,注:与内容无关的评论将被删除,严重者禁用帐号! |
&&|&&最新评论不吐不快,赶紧来一发!栏目推荐热门点击本站推荐
| 服务协议 | 隐私权保护 | 开放平台 | 广告服务 | PHP1招聘 | PHP1公益 | 客服中心
| Copyright (C) 1998 - . All Rights Reserved
第一PHP社区您现在的位置: &
PHP-redis中文文档介绍
PHP-redis中文文档介绍
    phpredis是php的一个扩展,效率是相当高有链表排序功能,对创建内存级的模块业务关系
  很有用;以下是redis官方提供的命令使用技巧:
  下载地址如下:
  (支持redis 2.0.4)Redis::__construct构造函数$redis = new Redis();connect, open 链接redis服务参数host: string,服务地址port: int,端口号timeout: float,链接时长 (可选, 默认为 0 ,不限链接时间)注: 在nf中也有时间,默认为300pconnect, popen 不会主动关闭的链接参考上面setOption 设置redis模式getOption 查看redis设置的模式ping 查看连接状态get 得到某个key的值(string值)如果该key不存在,return falseset 写入key 和 value(string值)如果写入成功,return turesetex 带生存时间的写入值$redis-&setex('key', 3600, 'value'); // sets key → value, with 1h TTL.setnx 判断是否重复的,写入值$redis-&setnx('key', 'value');$redis-&setnx('key', 'value');delete& 删除指定key的值返回已经删除key的个数(长整数)$redis-&delete('key1', 'key2');$redis-&delete(array('key3', 'key4', 'key5'));ttl得到一个key的生存时间persist移除生存时间到期的key如果key到期 true 如果不到期 falsemset (redis版本1.1以上才可以用)同时给多个key赋值$redis-&mset(array('key0' =& 'value0', 'key1' =& 'value1'));multi, exec, discard进入或者退出事务模式参数可选Redis::MULTI或Redis::PIPELINE. 默认是 Redis::MULTIRedis::MULTI:将多个操作当成一个事务执行Redis::PIPELINE:让(多条)执行命令简单的,更加快速的发送给服务器,但是没有任何原子性的保证discard:删除一个事务返回值multi(),返回一个redis对象,并进入multi-mode模式,一旦进入multi-mode模式,以后调用的所有方法都会返回相同的对象,只到exec()方法被调用。watch, unwatch (代码测试后,不能达到所说的效果)监测一个key的值是否被其它的程序更改。如果这个key在watch 和 exec (方法)间被修改,这个 MULTI/EXEC 事务的执行将失败(return false)unwatch& 取消被这个程序监测的所有key参数,一对key的列表$redis-&watch('x');$ret = $redis-&multi() -&incr('x') -&exec();subscribe *方法回调。注意,该方法可能在未来里发生改变publish *发表内容到某一个通道。注意,该方法可能在未来里发生改变exists判断key是否存在。存在 true 不在 falseincr, incrBykey中的值进行自增1,如果填写了第二个参数,者自增第二个参数所填的值$redis-&incr('key1');$redis-&incrBy('key1', 10);decr, decrBy做减法,使用方法同incrgetMultiple传参由key组成的数组返回参数如果key存在返回value,不存在返回false$redis-&set('key1', 'value1'); $redis-&set('key2', 'value2'); $redis-&set('key3', 'value3'); $redis-&getMultiple(array('key1', 'key2', 'key3'));$redis-&lRem('key1', 'A', 2);$redis-&lRange('key1', 0, -1);list相关操作lPush$redis-&lPush(key, value);在名称为key的list左边(头)添加一个值为value的&元素rPush$redis-&rPush(key, value);在名称为key的list右边(尾)添加一个值为value的&元素lPushx/rPushx$redis-&lPushx(key, value);在名称为key的list左边(头)/右边(尾)添加一个值为value的元素,如果value已经存在,则不添加lPop/rPop$redis-&lPop('key');输出名称为key的list左(头)起/右(尾)起的第一个元素,删除该元素blPop/brPop$redis-&blPop('key1', 'key2', 10);lpop命令的block版本。即当timeout为0时,若遇到名称为key&i的list不存在或该list为空,则命令结束。如果timeout&0,则遇到上述情况时,等待timeout秒,如果问题没有解决,则对keyi+1开始的list执行pop操作lSize$redis-&lSize('key');返回名称为key的list有多少个元素lIndex, lGet$redis-&lGet('key', 0);返回名称为key的list中index位置的元素lSet$redis-&lSet('key', 0, 'X');给名称为key的list中index位置的元素赋值为valuelRange, lGetRange$redis-&lRange('key1', 0, -1);返回名称为key的list中start至end之间的元素(end为 -1 ,返回所有)lTrim, listTrim$redis-&lTrim('key', start, end);截取名称为key的list,保留start至end之间的元素lRem, lRemove$redis-&lRem('key', 'A', 2);删除count个名称为key的list中值为value的元素。count为0,删除所有值为value的元素,count&0从头至尾删除count个值为value的元素,count&0从尾到头删除|count|个值为value的元素lInsert在名称为为key的list中,找到值为pivot 的value,并根据参数Redis::BEFORE | Redis::AFTER,来确定,newvalue 是放在 pivot 的前面,或者后面。如果key不存在,不会插入,如果 pivot不存在,return -1$redis-&delete('key1'); $redis-&lInsert('key1', Redis::AFTER, 'A', 'X'); $redis-&lPush('key1', 'A'); $redis-&lPush('key1', 'B'); $redis-&lPush('key1', 'C'); $redis-&lInsert('key1', Redis::BEFORE, 'C', 'X');$redis-&lRange('key1', 0, -1);$redis-&lInsert('key1', Redis::AFTER, 'C', 'Y');$redis-&lRange('key1', 0, -1);$redis-&lInsert('key1', Redis::AFTER, 'W', 'value');rpoplpush返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部$redis-&delete('x', 'y');$redis-&lPush('x', 'abc'); $redis-&lPush('x', 'def'); $redis-&lPush('y', '123'); $redis-&lPush('y', '456'); // move the last of x to the front of y. var_dump($redis-&rpoplpush('x', 'y'));var_dump($redis-&lRange('x', 0, -1));var_dump($redis-&lRange('y', 0, -1)); string(3) "abc" array(1) { [0]=& string(3) "def" } array(3) { [0]=& string(3) "abc" [1]=& string(3) "456" [2]=& string(3) "123" }SET操作相关sAdd向名称为key的set中添加元素value,如果value存在,不写入,return false$redis-&sAdd(key , value);sRem, sRemove删除名称为key的set中的元素value$redis-&sAdd('key1' , 'set1');$redis-&sAdd('key1' , 'set2');$redis-&sAdd('key1' , 'set3');$redis-&sRem('key1', 'set2');sMove将value元素从名称为srckey的集合移到名称为dstkey的集合$redis-&sMove(seckey, dstkey, value);sIsMember, sContains名称为key的集合中查找是否有value元素,有ture 没有 false$redis-&sIsMember(key, value);sCard, sSize返回名称为key的set的元素个数sPop随机返回并删除名称为key的set中一个元素sRandMember随机返回名称为key的set中一个元素,不删除sInter求交集sInterStore求交集并将交集保存到output的集合$redis-&sInterStore('output', 'key1', 'key2', 'key3')sUnion求并集$redis-&sUnion('s0', 's1', 's2');s0,s1,s2 同时求并集sUnionStore求并集并将并集保存到output的集合$redis-&sUnionStore('output', 'key1', 'key2', 'key3');sDiff求差集sDiffStore求差集并将差集保存到output的集合sMembers, sGetMembers返回名称为key的set的所有元素sort排序,分页等参数'by' =& 'some_pattern_*','limit' =& array(0, 1),'get' =& 'some_other_pattern_*' or an array of patterns,'sort' =& 'asc' or 'desc','alpha' =& TRUE,'store' =& 'external-key'例子$redis-&delete('s'); $redis-&sadd('s', 5); $redis-&sadd('s', 4); $redis-&sadd('s', 2); $redis-&sadd('s', 1); $redis-&sadd('s', 3);var_dump($redis-&sort('s')); // 1,2,3,4,5var_dump($redis-&sort('s', array('sort' =& 'desc'))); // 5,4,3,2,1var_dump($redis-&sort('s', array('sort' =& 'desc', 'store' =& 'out'))); // (int)5string命令getSet返回原来key中的值,并将value写入key$redis-&set('x', '42');$exValue = $redis-&getSet('x', 'lol'); // return '42', replaces x by 'lol'$newValue = $redis-&get('x')' // return 'lol'appendstring,名称为key的string的值在后面加上value$redis-&set('key', 'value1');$redis-&append('key', 'value2');$redis-&get('key');getRange (方法不存在)返回名称为key的string中start至end之间的字符$redis-&set('key', 'string value');$redis-&getRange('key', 0, 5);$redis-&getRange('key', -5, -1);setRange (方法不存在)改变key的string中start至end之间的字符为value$redis-&set('key', 'Hello world');$redis-&setRange('key', 6, "redis");$redis-&get('key');strlen得到key的string的长度$redis-&strlen('key');getBit/setBit返回2进制信息zset(sorted set)操作相关zAdd(key, score, member):向名称为key的zset中添加元素member,score用于排序。如果该元素已经存在,则根据score更新该元素的顺序。$redis-&zAdd('key', 1, 'val1');$redis-&zAdd('key', 0, 'val0');$redis-&zAdd('key', 5, 'val5');$redis-&zRange('key', 0, -1); // array(val0, val1, val5)zRange(key, start, end,withscores):返回名称为key的zset(元素已按score从小到大排序)中的index从start到end的所有元素$redis-&zAdd('key1', 0, 'val0');$redis-&zAdd('key1', 2, 'val2');$redis-&zAdd('key1', 10, 'val10');$redis-&zRange('key1', 0, -1); // with scores $redis-&zRange('key1', 0, -1, true);zDelete, zRemzRem(key, member)&:删除名称为key的zset中的元素member$redis-&zAdd('key', 0, 'val0');$redis-&zAdd('key', 2, 'val2');$redis-&zAdd('key', 10, 'val10');$redis-&zDelete('key', 'val2');$redis-&zRange('key', 0, -1); zRevRange(key, start, end,withscores):返回名称为key的zset(元素已按score从大到小排序)中的index从start到end的所有元素.withscores: 是否输出socre的值,默认false,不输出$redis-&zAdd('key', 0, 'val0');$redis-&zAdd('key', 2, 'val2');$redis-&zAdd('key', 10, 'val10');$redis-&zRevRange('key', 0, -1); // with scores $redis-&zRevRange('key', 0, -1, true);zRangeByScore, zRevRangeByScore$redis-&zRangeByScore(key, star, end, array(withscores, limit ));返回名称为key的zset中score &= star且score &= end的所有元素zCount$redis-&zCount(key, star, end);返回名称为key的zset中score &= star且score &= end的所有元素的个数zRemRangeByScore, zDeleteRangeByScore$redis-&zRemRangeByScore('key', star, end);删除名称为key的zset中score &= star且score &= end的所有元素,返回删除个数zSize, zCard返回名称为key的zset的所有元素的个数zScore$redis-&zScore(key, val2);返回名称为key的zset中元素val2的scorezRank, zRevRank$redis-&zRevRank(key, val);返回名称为key的zset(元素已按score从小到大排序)中val元素的rank(即index,从0开始),若没有val元素,返回“null”。zRevRank 是从大到小排序zIncrBy$redis-&zIncrBy('key', increment, 'member');如果在名称为key的zset中已经存在元素member,则该元素的score增加increment;否则向集合中添加该元素,其score的值为incrementzUnion/zInter参数keyOutputarrayZSetKeysarrayWeightsaggregateFunction Either "SUM", "MIN", or "MAX": defines the behaviour to use on duplicate entries during the zUnion.对N个zset求并集和交集,并将最后的集合保存在dstkeyN中。对于集合中每一个元素的score,在进行AGGREGATE运算前,都要乘以对于的WEIGHT参数。如果没有提供WEIGHT,默认为1。默认的AGGREGATE是SUM,即结果集合中元素的score是所有集合对应元素进行SUM运算的值,而MIN和MAX是指,结果集合中元素的score是所有集合对应元素中最小值和最大值。Hash操作hSet$redis-&hSet('h', 'key1', 'hello');向名称为h的hash中添加元素key1―&hellohGet$redis-&hGet('h', 'key1');返回名称为h的hash中key1对应的value(hello)hLen$redis-&hLen('h');返回名称为h的hash中元素个数hDel$redis-&hDel('h', 'key1');删除名称为h的hash中键为key1的域hKeys$redis-&hKeys('h');返回名称为key的hash中所有键hVals$redis-&hVals('h')返回名称为h的hash中所有键对应的valuehGetAll$redis-&hGetAll('h');返回名称为h的hash中所有的键(field)及其对应的valuehExists$redis-&hExists('h', 'a');名称为h的hash中是否存在键名字为a的域hIncrBy$redis-&hIncrBy('h', 'x', 2);将名称为h的hash中x的value增加2hMset$redis-&hMset('user:1', array('name' =& 'Joe', 'salary' =& 2000));向名称为key的hash中批量添加元素hMGet$redis-&hmGet('h', array('field1', 'field2'));返回名称为h的hash中field1,field2对应的valueredis 操作相关flushDB清空当前数据库flushAll清空所有数据库randomKey随机返回key空间的一个key$key = $redis-&randomKey();select选择一个数据库move转移一个key到另外一个数据库$redis-&select(0); // switch to DB 0$redis-&set('x', '42'); // write 42 to x$redis-&move('x', 1); // move to DB 1$redis-&select(1); // switch to DB 1$redis-&get('x'); // will return 42rename, renameKey给key重命名$redis-&set('x', '42');$redis-&rename('x', 'y');$redis-&get('y'); // → 42$redis-&get('x'); // → `FALSE`renameNx与remane类似,但是,如果重新命名的名字已经存在,不会替换成功setTimeout, expire设定一个key的活动时间(s)$redis-&setTimeout('x', 3);expireAtkey存活到一个unix时间戳时间$redis-&expireAt('x', time() + 3);keys, getKeys返回满足给定pattern的所有key$keyWithUserPrefix = $redis-&keys('user*');dbSize查看现在数据库有多少key$count = $redis-&dbSize();auth密码认证$redis-&auth('foobared');bgrewriteaof使用aof来进行数据库持久化$redis-&bgrewriteaof();slaveof选择从服务器$redis-&slaveof('10.0.1.7', 6379);save将数据同步保存到磁盘bgsave将数据异步保存到磁盘lastSave返回上次成功将数据保存到磁盘的Unix时戳info返回redis的版本信息等详情type返回key的类型值string: Redis::REDIS_STRINGset: Redis::REDIS_SETlist: Redis::REDIS_LISTzset: Redis::REDIS_ZSEThash: Redis::REDIS_HASHother: Redis::REDIS_NOT_FOUND
&&&主编推荐
&&&热门试卷
&&&最新视频
&&&热门阅读
&&&最新问答
&&&&&&&&&&&&&&&
希赛网 版权所有 & &&&&湘教QS2-164&&增值电信业务经营许可证湘B2-}

我要回帖

更多关于 mac php redis 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信