利用Redis cache优化app查询速度实践
注意:本篇文章译自speeding up existing app with a redis cache,如需要转载请注明出处。
发现问题
在应用解决方法之前,我们需要对我们面对的问题有一个清晰的认识。
App所遇到的问题是,当执行一个查询时,它会跑到Diffbot’s API 然后查询数据集。子集被返回并展示出来。根据Diffbot服务器的繁忙程度,可能需要花5秒左右的时间去完成这一过程。如果扩展计算机的能力这种情形无疑会改进,如果一个查询执行一次就被记住并且重复使用24小时,通常可以把这个过程看成刷新这个集合,并且这个方式会非常的高效。
你可能会怀疑“缓存一个查询有什么好处呢?”大多数人应该都不会只查询一个东西或者同样的事物。
呃...事实上,不仅调查表明人们经常查询一个事情或相同的事,他们通常也会去搜索多产作家(或自己)。考虑到事实上应用这一缓存方式并没有增加纸面上的成本(其实是通过减少服务器压力而减少成本),把这个加进来是一个容易的盈利点,即使它使用频率并没有我们希望那样高。但我们也没有任何理由不使用它----因为它可以给我们带来利益。
既然问题已经界定清楚,让我们先处理先决条件。
配置环境
首先,我们需要在开发和生产环境下安装Redis(需要注意的是,如果你把Homestead用于本地开发,Redis就已经安装好了,目前使用的是v3.0.1版本)
我们可以通过操作系统的包管理器来做这件事:
- sudo apt-get install redis-server
这是最简单也是最为推荐的方法,但我们也可以从头来安装并且手动配置。根据他们网上的说明,我们可以如此配置:
- sudo apt-get install gcc make build-essential tcl
- wget http://download.redis.io/releases/redis-3.0.2.tar.gz
- tar xzf redis-3.0..tar.gz
- cd redis-3.0.
- make
- make test
- sudo make install
如果你运行make
遇到错误提示jemalloc.h
那么运行make distclean
然后在运行make
。make test
命令是选择性运行的,但是很有帮助。
注意:如果你看到这里,而3.0.2已经不是最新的版本,那么根据你的最新版本号去调节命令。
为了防止一些常见的警告(至少在Ubuntu上),我们还需要预防性的运行以下命令:
- sudo sh -c 'echo "vm.overcommit_memory=1" >> /etc/sysctl.conf'
- sudo sh -c 'echo "net.core.somaxconn=65535" >> /etc/sysctl.conf'
- sudo sh -c 'echo "never" > /sys/kernel/mm/transparent_hugepage/enabled'
我们也要确保最后的命令在exit 0
上被添加到了/etc/rc.local
,因此能保证在每个重启的服务器上能重新发送。最后我们可以用sudo reboot
重启服务器并且运行有sudo redis-server
的Redis检查是否一切正常。
最后,我们要确保在服务器重启后Redis会启动,所以我们要跟着官方的说明去完成配置。
Predis
我们之前说了一些关于Predis的基础知识,我们将要将其用到本文的例子中:
- composer require predis/predis
进一步的,假设我们已经了解之前叙述的关于Predis的知识。
和之前发表的关于Predis相比,虽然是有一些不同(比如过渡到命名空间),但我们需要的API几乎是一样的。
实施
要在我们app里运用Redis,我们需要遵循以下的程序:
- 查看当前的缓存中是否有查询结果
- 如果是,抓取他们
- 如果没有,把他们拿来,储存,将他们发送到app的其他部分
因此,实施非常的简单:在“form submitted”下检查(寻找“search”参数),我们实例化Predis客户端,计算search查询的MD5 hash值,然后检查查询结果是否已经被缓存。如果失败,就在重复前面的流程。
- $result = ...
- $info = ...
我们将查询结果序列化并直接保存到cache里。然后我们在模块外立即抓取他们,app的流程就和往常一样继续。而index.php改变的部分如下:
- // Check if the search form was submitted
- if (isset($queryParams['search'])) {
- $redis = new Client();
- $hash = md5($_SERVER['QUERY_STRING']);
- if (!$redis->get($hash . '-results')) {
- $diffbot = new Diffbot(DIFFBOT_TOKEN);
- // Building the search string
- $searchHelper = new SearchHelper();
- $string = (isset($queryParams['q']) && !empty($queryParams['q']))
- ? $queryParams['q']
- : $searchHelper->stringFromParams($queryParams);
- // Basics
- $search = $diffbot
- ->search($string)
- ->setCol('sp_search')
- ->setStart(($queryParams['page'] - ) * $resultsPerPage)
- ->setNum($resultsPerPage);
- $redis->set($hash . '-results', serialize($search->call()));
- $redis->expire($hash . '-results', );
- $redis->set($hash . '-info', serialize($search->call(true)));
- $redis->expire($hash . '-info', );
- }
- $results = unserialize($redis->get($hash . '-results'));
- $info = unserialize($redis->get($hash . '-info'));
进过测试,我们可以看到它的魅力所在—如果我们刷新页面,或执行另一个查询,就会立即执行一次查询,然后会回到之前的那个。最后我们添加,提交,推动部署一下内容:
- git add -A
- git commit -m "Added Redis cache [deploy:production]"
- git push origin master
就是这么简单,我们的最新版的app已经上线,而且使用的Redis。
注意:如果你想知道我们是如何用一条命令从开发模式转到生产部署,你可以看这里。
微调
为了进一步的提升性能,Predis推荐安装phpiredis,这是个PHP的扩展,目的是“降低序列化和解析Redis协议的成本”。可以看作我们完全控制了服务器,有什么理由不试试呢?
- cd ~
- git clone https://github.com/redis/hiredis
- cd hiredis
- make
- sudo make install
- cd ~
- git clone https://github.com/nrk/phpiredis
- cd phpiredis
- phpize && ./configure --enable-phpiredis
- make
- sudo make install
- sudo touch /etc/php5/mods-available/phpiredis.ini
- sudo sh -c 'echo "extension=phpiredis.so" > /etc/php5/mods-available/phpiredis.ini'
- sudo php5enmod phpiredis
- sudo service php5-fpm restart
以上是安装的前提,并且启用了扩展。现在我们要做的就是利用phpiredis链接去配置Predis客户端。因此我们需要更换:
- $redis = new Client();
和
- $redis = new Client('tcp://127.0.0.1', [
- 'connections' => [
- 'tcp' => 'Predis\Connection\PhpiredisStreamConnection',
- 'unix' => 'Predis\Connection\PhpiredisSocketConnection',
- ],
- ]);
就是这么简单!现在我们的Redis安装会更快!
总结:
在本教程中,我们利用Redis结合Predis库来提升已部署的app的速度,我们平衡大数据海洋的水滴中可用的RAM来存储每天一次查询的结果,然后从缓存中返回这些结果,而不是重新运行一遍查询。但这确实意味着结果不会总是最新的,但就这边文章,其实查询结果没有被刷新的次数比这种情况多得多。
注:关于更多的有关Redis的知识可以参考redisdoc.com (此网站文档是 Redis Command Reference 和 Redis Documentation 的中文翻译版, 阅读这个文档可以帮助你了解 Redis 命令的具体使用方法, 并学会如何使用 Redis 的事务、持久化、复制、Sentinel、集群等功能。)
我们云巴的产品也是使用redis存储实践,大家也可以来交流学习~
利用Redis cache优化app查询速度实践的更多相关文章
- Android 优化APP 构建速度的17条建议
转载:http://www.jianshu.com/p/a1cc8f2e0877 较长的构建时间将会减缓项目的开发进度,特别是对于大型的项目,app的构建时间长则十几分钟,短则几分钟,长的构建时间已经 ...
- 如何优化mysql查询速度
1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. 2.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉 ...
- 利用 Redis 来优化功能部署和错误分类
来源:Redislabs 作者:Shabih Syed 翻译:Kevin (公众号:中间件小哥) 为了让系统运行更流畅,又避免 Knights Capital 在 2012 年犯下的 4.6 亿美元的 ...
- BLOB或TEXT字段使用散列值和前缀索引优化提高查询速度
1.创建表,存储引擎为myisam,对大文本字段blob使用MD5函数建立一个散列值 create table t2(id varchar(60), content blob, hash_value ...
- 对sql server查询速度的优化
处理百万级以上的数据提高查询速度的方法: 1.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. 2.对查询进行优化,应尽量避免全表扫描,首先应考 ...
- mysql处理海量数据时的一些优化查询速度方法
最近一段时间由于工作需要,开始关注针对Mysql数据库的select查询语句的相关优化方法. 由于在参与的实际项目中发现当mysql表的数据量达到百万级时,普通SQL查询效率呈直线下降,而且如果w ...
- 提高查询速度:SQL Server数据库优化方案
查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 ...
- 利用Azure Redis Cache构建百万量级缓存读写
Redis是一个非常流行的基于内存的,低延迟,高吞吐量的key/value数据存储,被广泛用于数据库缓存,session的管理,热数据高速访问,甚至作为数据库方式提高应用程序可扩展性,吞吐量,和实施处 ...
- 优化SQLServer数据库加快查询速度
查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 ...
随机推荐
- Atitit 发帖机实现(1)-----UsrQBm2008 页面上下文规范
Atitit 发帖机实现(1)-----UsrQBm2008 页面上下文规范 1.1. 网站绝对路径,页面绝对路径1 1.2. Java的javax.servlet.ServletContext1 ...
- fir.im Weekly - 17 个提升 iOS 开发效率的必备工具
本期 fir.im Weekly 精选了一些iOS 开发工具和动画源码分享,希望每个开发者能专注效率.实用.灵感. iOS开发工具--如何优化ipa包大小 @iOS程序犭袁 推荐了关于"如 ...
- asp.net mvc 使用ajax请求 控制器 (PartialViewResult)分部的action,得到一个分部视图(PartialView)的HTML,进行渲染
在asp.net mvc 使用ajax请求获取数据的时候,我们一般是返回json或者xml,然后解析这些数据进行渲染,这样会比较麻烦,可以请求一个 分部action,返回一个分部视图 直接可以渲染,不 ...
- vuejs动态组件给子组件传递数据
vuejs动态组件给子组件传递数据 通过子组件定义时候的props可以支持父组件给子组件传递数据,这些定义的props在子组件的标签中使用绑定属性即可,但是如果使用的是<component> ...
- 【原创】Matlab.NET混合编程技巧之找出Matlab内置函数
本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 Matlab和C#混合编程文章目录 :[目录]Matlab和C#混合编程文章目录 Matlab与.N ...
- 【目录】微软Infer.NET机器学习组件文章目录
本博客所有文章分类的总目录链接:http://www.cnblogs.com/asxinyu/p/4288836.html 1.微软Infer.NET机器学习组件目录 1. Infer.NET连载(一 ...
- iOS_UIImage_裁切圆形头像
github地址: https://github.com/mancongiOS/UIImage.git UIImage的Cagetory UIImage+ImageCircle.h - (UIImag ...
- js基础篇——encodeURI 和encodeURIComponent
转自zccst的又一次掉进encodeURIComponent的坑里了 问题: ajax.get ( url+'?k1'=v1+'&k2'=v2+'&k3'=v3, ... ); 由于 ...
- 阅读《LEARNING HARD C#学习笔记》知识点总结与摘要四
又是一个周末,刚好有时间,又继续复习与总结了,希望能让大家受益,不足之处欢迎指正,谢谢! 十八. Lambda 1.Lambda表达式:匿名方法的另一种表现形式,它可以包含表达式和语句,且用于创建委托 ...
- 前端构建:Source Maps详解
一.前言 当使用CoffeeScript.ClojureScript编写前端脚本时,当使用Less.Sacc编写样式规则时,是否觉得调试时无法准确找到源码位置呢?当使用jquery.min.js等经压 ...