前方高能,前排预警,大量图文!!! 手机看帖的小伙子请注意你的流量套餐!!!
好了,切入正题。
在关系型数据库一统天下的时候,有一个意大利人开发出了一种非关系型数据库 Redis,用来解决关系型数据库在面对大流量高并发产生的数据库巨大读写压力,Redis以高效的读写效率闻名,比起memcache, Redis拥有更多的数据类型,在面对复杂的应用场景时,有着更多更合适的类型选择。所以为什么我们要用Redis?因为传统的结构严谨的关系型数据库,其劣势是在大量读写压力之下,性能下降得非常明显,这个时候项目的用户体验就会明显下降,我们不得不引入Redis来充当程序跟数据库之间的一个桥梁,帮助缓解关系型数据库的压力,但是Redis并不能取代传统的关系型数据库(比如mysql) ,因为大量的应用数据需要持久化写入硬盘,而Redis的持久化并不十分理想(下面会给大家介绍),所以Redis起的是一个辅助作用。
首先回顾下Redis的基础知识( 我们这里不讲拗口难懂的名词 )
1 什么是Redis?
答:一种nosql数据库(非关系形数据库)。
2 为什么要用Redis?
答:缓解数据库压力
3 Redis有哪几种数据类型?
1 字符串(string) 2 哈希( hash ) 3 队列(list) 4 集合(set) 5 有序集合(sorted set)
如果对于Redis数据类型不太了解的可以自行百度,本章不作科普,显得太啰嗦。
知识这个东西,除了了解之外,必须加以实践对不对?马上给大家奉上干货,由于之前的开发的源码找不到了,在下只好重新简单地写了几个demo ,旨在传达思想,不作为具体的应用最佳实现,以下基于PHP向大家讲解。
注意:Redis所有的数据类型的存储都是基于key=>value的方式来保存的
字符串(string)
最简单,应用最多的一个数据类型。
比如我们网站有一个需求是要求用户请求短信接口,我们需要判断用户在一分钟内不能再次发起请求,必须至少等待一分钟。
那么剖析一下这个需求,2个点
1:一个用户(其实就是手机号)
2:单位时间 (可以想到就是过期时间)
因为Redis的所有键都是可以设置过期时间的,那么解决思路是把请求的用户手机号+1分钟的存储时间
模拟代码:
<?php
include_once("./RedisService.class.php");
$redis = new RedisService();
$mobile='137****7242';//任意一个手机号
$expire=60;
$keyName="message:".$mobile;
if($redis->get($keyName))
{
die("一分钟内不能频繁请求");
}
$re=$redis->set($keyName,1,$expire);
if($re)
{
echo '发送成功';
}
那么在第一次运行此代码的时候,如下:

由于Redis中并没有该用户的数据,所以会往Redis中写入该用户的信息

我们定义键名的时候要以:来间隔,这样可以生成如图所示的层级目录,方便查看管理。
可以看到我们定义的键名是message:137****7242 ,键值是1 ,TTL是过期时间,截图的时候已经不足一分钟
那么我们再次运行此代码可以看到:

因为Redis中已经存在该用户的发送信息了,那么在一分钟内再次请求都会被拦截下来
一分钟后可以看到redis中的message:137****7242这个键已经不见了(过期清理):

这个时候我们再次请求:

可以发现又请求成功了
这也就实现了对用户单位时间内请求次数的限制,结合实际项目可以做一些相应的扩展。
string类型最经常的情况下的是拿来做缓存的。
像一些高频访问的数据,但是又不是更新很频繁的,就适合缓存起来。
比如首页有个热门菜谱这么一个列表,显示10条菜谱,那么这个就是热点数据,因为访问频率是最高的,如果采用去mysql中查询的方式,那么在菜谱表数据量一上来,过了百万级,查询效率就下降比较明显了。另外一个是日后用户量一增加,数据库的吞吐量不足的话,也会使得查询效率明显降低,那么我们可以选择把这部分热点数据给缓存到Redis中去,之后的所有数据读取都不经过数据库,都会到Redis中去读取数据
模拟代码:
<?php
include_once("./RedisService.class.php");
include_once("./Mysql.class.php");
$db = new Mysql();
$redis = new RedisService();
$keyName="dishes:hot:top10";
//如果有缓存
if($hotDishes=unserialize($redis->get($keyName)))
{
echo '从缓存中获得这些数据:<br>';
var_dump($hotDishes);
}
else
{
//没有缓存,查询数据库
$sql="select dishes_id,dishes_name,dishes_image from dishes where is_hot =1 order by dishes_id DESC limit 10";
$hotDishes=$db->query($sql);
if(!empty($hotDishes))
{
//写入Redis
$redis->set($keyName,serialize($hotDishes),3600*2);
}
var_dump($hotDishes);
}
那么我们来看看效果先 ,一会再讲解
第一次运行此代码的时候可以看到查出来10条数据:

以及在Redis中生成了缓存:

缓存的时间TTL是我们设置的两个小时,注意因为Redis的string类型只能存储字符串,所以我们的数组要经过serialize()序列化之后才可以存储,同理取出的时候也要反序列化(见代码)。那么在两个小时之内我们都可以通过读取缓存来获取这个数据,再次访问:

这就是string 类型用于数据缓存的基本用法。
哈希类型(hash)
哈希类型最典型的一个应用,就是作为Session的替换方案,在单机服务器的时候我们可能没有感觉到Session的潜在问题,可是如果日后业务发展加快,需要水平扩展服务器的时候(负载均衡),Session共享就会成为一个问题,虽说nginx有根据IP分发请求的策略,但不是最优解,我们最理想的是可以实现所有Session的集中管理。
这里我们只做最最简单的演示 , 在实际的登陆中还有非常多的验证:
<?php
include_once("./RedisService.class.php");
include_once("./Mysql.class.php");
$db = new Mysql();
$redis = new RedisService();
$username=$_POST['username'];
$password=$_POST['password'];
$sql="select * from pr_user where user = '$username'";
$re=$db->query($sql);
if($re[0]['pass']==md5($password.'zc'))
{
//生成SESSION
$session_id=getRandomString(20);
$session_redis_key="session:".date("Y-m-d",time()).":".$session_id;
unset($re[0]['pass']);
//写入Redis
$redis->hashSet($session_redis_key,$re[0],3600*2);
//写入数据库
$sql="update pr_user set session_id = '$session_id'";
$setRe=$db->query($sql);
if($setRe)
{
//设置cookie
setCookie("session_id",$session_id);
echo 'login successfully';
}
}
function getRandomString($len, $chars=null)
{
if (is_null($chars)){
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
}
mt_srand(10000000*(double)microtime());
for ($i = 0, $str = '', $lc = strlen($chars)-1; $i < $len; $i++){
$str .= $chars[mt_rand(0, $lc)];
}
return $str;
}
我们要做的就是模拟session_id 用20位的随机数来代表session_id,Redis键名用 'session:日期:session_id'

最低0.47元/天 解锁文章

150

被折叠的 条评论
为什么被折叠?



