一.过期时间
在实际的开发中我们经常遇到一些有时效的数据,在Redis中我们应该怎样处理这些数据呢?
下面来学习:
1.EXPIRE命令
我们可以使用它来设置一个键的过期时间,到时间后Redis会自动删除它。
例如
SET session:23 uid1314
EXPIRE session:23 30//单位为秒
上面返回1表示执行成功,如果返回0则表示键不存在或者失败。
2.TTL命令
如果我们想知道我们设置自动删除的键还有多久会删除,我们可以用TTL来查询:
当键不存在时会返回-2 :
返回-1则表示改键永久存在:
3.PERSIST命令
如果我们想取消键的过期时间设置(就是将键设置为永久的),我们可以用这个
注意:除了PERSIST命令外,我们还可以用SET或者GETSET命令在为键赋值的同时也清除过期时间设置,也可以用EXPIRE为键重新设置过期时间。
细节:如果使用WATCH命令监视了一个拥有过期时间的键,该键时间到期自动删除并不会被WATCH命令认为该键被改变
4.应用场景
1).实现访问频率限制
例如我们要限制每分钟每个用户最多只能访问100个页面,基本的思路就是:
a.对每一个用户使用一个名为rate.limiting:用户IP 的字符串类型的键。
b.每次用户访问则使用INCR命令递增该键的键值,如果递增后的值为1,则同时还要设置改键的过期时间为1分钟。
c.这样每次用户访问页面时都增加改键的键值,如果达到100就提示用户稍后访问,知道该键被删除,用户就又可以重新访问了。
我们开始也许会认为上面的思路没啥问题,但当我们仔细的想想,会发现这样一种情况:
某个用户在第1秒访问1次,在第60秒访问99次,改键被删除,然后再进行访问在第1秒访问100次,这样的话,该用户在2秒访问了199次!!
我们如果需要精确的控制的话,我们需要记录下用户每次访问的时间,因此对每个用户:
a.我们使用一个列表类型的键来记录它最近100次访问网页的时间。
b.一旦键中的元素超过100个,就判断时间最早的元素距现在的时间是否小于1分钟:
如果是则表示用户最近1分钟的访问次数超过了100次。
如果不是则将现在的时间加入到列表中,同时把最早的元素删除。
2)实现缓存
为了提高网站的负载能力,常常需要将一些访问频率较高但对CPU或IO资源消耗较大的操作结果缓存起来,相当于一个Cache,并希望让这些缓存过一段时间失效,这时候我们就可以用过期时间来实现。
例如:
一个成绩排名网站要对所有用户的成绩汇总排名,并在首页上显示前10名的学生姓名。
由于计算过程比较消耗资源,于是将结果使用一个Redis的字符串缓存起来。
但由于用户的成绩总在不断变化,需要每隔两个小时就重新计算排名,这时候我们可以通过给键设置过期时间。
每次用户访问首页的时候程序先查询缓存键是否存在,如果存在则直接使用缓存的值,否则重新计算并将计算结果赋给该键并设置过期时间。
注意:
但是我们不能滥用这个技术,特别是当服务器内存有限时,如果大量使用缓存键且过期时间设置的过长就会导致Redis占满内存,另一方面如果为了防止Redis占用内存过大而将缓存的过期时间设置的过短又会导致缓存命中率降低,所以:如何为Redis缓存键设置过期时间是对我们的能力的一种考验
一般的做法为:限制Redis能够只用的最大内存,并让Redis按照一定的规则淘汰不需要的缓存键。
具体的设置方法为:修改配置文件的maxmemory参数,限制Redis最大可用内存大小,当超过了这个限制时Redis会依据maxmemory-policy参数指定的策略来删除不需要的键直到Redis占用的字节内存小于指定内存。
删除键的规则有如下:
规则 | 说明 |
---|---|
volatile-lru | 使用LRU算法删除一个键(只对设置了过期时间的键) |
allkeys-lru | 使用LRU算法删除一个键 |
volatile-random | 随机删除一个键(只对设置了过期时间的键) |
allkeys-random | 随机删除一个键 |
volatile-ttl | 删除过期时间最近的一个键 |
noeviction | 不删除键,只返回错误 |
LRU算法的思想是:删除最近最少使用的缓存
二.排序
1.SORT命令
除了使用有序集合之外我们还可以借助Redis提供的SORT命令来解决一些问题。
SORT命令可以对列表类型,集合类型和有序集合类型键进行排序,并且可以完成与关系型数据库中的连接查询类似的任务。
1)对列表排序
2.对有序集合排序(注意在对有序集合进行排序时会忽略分数,只针对元素自身的值进行排序)
除了对数字排序以外,还支持字符排序(注意和上面的略有不同):
还可以降序排序:
2.LIMIT命令
和MySQL一样限制查询(从0开始)
3.BY参数
BY参数可以让我们的SORT命令将不再依赖元素自身的值进行排序,而是对每个元素使用元素的值替换参考键中第一个“*”并获取其值,然后依据该值对元素排序:
4.GET参数
GET参数不影响排序,它的作用是使SORT命令的返回结果不再是元素自身的值,而是GET参数中指定的键值。
5.STORE参数
默认情况下SORT会直接返回排序结果,如果希望保存排序结果,可以使用STORE参数
三.性能优化
SORT是Redis中最强大且最复杂的命令之一,使用时一定要谨慎!!
这个命令的时间复杂度为 O(n+mlog(m)) , 其中n为排序集合元素个数,m为要返回的元素个数,所以我们在使用时一定要让n和m尽可能的小。
我们可以:
1)尽可能减少待排序键中元素的个数n
2)使用LIMIT来减少m
3)如果要排序的数据量较大,尽可能使用STORE参数将结果缓存