您的位置:首页 > 数据库 > Redis

Redis需特别注意的场景

2016-05-25 16:08 771 查看
Redis需特别注意的场景

1、 时间复杂度大O(Big ONotation)

当问题的规模,不断变化,执行时间也会不断变化。这就是时间复杂度大O的概念。对于Redis来说,时间复杂度可以用来描述在某个场景的数据规模下,一个命令会有多快。

Redis文档会告诉我们每一个命令的时间复杂度,它也会告诉我们影响命令性能的关键因素。

我们这里举几个例子:

O(1) 可以表示使用时间最短的。例如,sismember,Redis还有好多命令也都是O(1).

O(log(N)) 使用时间仅次于O(1)。例如,zadd。

O(N)属于线性的,在关系型数据库中,查找没有索引的列,就是O(N)的操作。Redis中的ltrim也是O(N)的操作。不过,这个N不是列表的个数,而是要删除的元素个数。

O(log(N)+M) 比线性使用时间还长。例如,zremrangebyscore,删除有序集合中排序在某个区间段上的数据。N是集合的元素个数,M是要删除的元素个数。

O(N+M*log(M)),是Redis中时间复杂度最高的。例如,sort

2、 伪多键查询(PseudoMulti Key Queries)

有一个很常见的情况,你要通过多个key,查询同一个value。比如,你既想通过email 查询用户数据,也想通过id查询用户数据。一个非常可怕的解决办法,就是再复杂一份value,类似下面的。

set users:test@sina.com  '{"id": 123, "name":"test", "email": "test@sina.com", ...}'
set users:123  '{"id": 123, "name":"test", "email": "test@sina.com", ...}'


一个比较好的解决办法,应该使用Redis的hash。

set users:123  '{"id": 123, "name":"test", "email": "test@sina.com", ...}'
hset users:id:email test@sina.com 123
如果想通过id找到用户,可以直接使用命令:

get users:123

如果想通过email找到用户,需要执行两个命令:

hget users:id:email test@sina.com
get users:#{上面命令的返回值}
3、 管道(Pipeline)

Redis还支持管道。通常情况下,客户端每个请求命令发出后,会阻塞,等待redis服务处理,Redis处理完后请求命令后会将结构通过响应报文返回给client。利用管道模式,我们可以从客户端发出多条命令,不需要等待单条命令的返回,Redis服务端会将多条命令的处理结果打包一起返回给客户端。这减少网络开销,性能得到显著提升。 利用Pipeline打包命令发送,Redis必须在处理完所有命令前线缓存起所有命令的处理结果。打包的命令越多,缓存消耗内存也越多。所以并不是打包的命令越多越好。具体多少合适需要根据情况测试。下面是Jedis客户端利用Pipeline的一段代码。

public void usePipeline(int count){
Jedisjr = null;
try{
jr= new Jedis("10.10.232.123", 6379);
Pipelinepl = jr.pipelined();
for(inti =0; i<count; i++){
pl.incr("key");
}
pl.sync();
}catch (Exception e) {
e.printStackTrace();
}finally{
if(jr!=null){
jr.disconnect();
}
}
4、 事务(Transactions)

Redis的每个命令都是原子的,包括那些需要多步操作的命令(incr,getset,setnx)。

Redis提供了事务机制,可以把多个命令作为一个原子性操作组执行。步骤很简单,先执行multi命令,跟着执行你的命令,最后可以执行exec命令提交所有操作,也可以执行discard命令放弃所有操作。先看看Redis对于事务的都有哪些要素:

(1)、全部命令会被顺序执行。

(2)、全部命令执行不会被打断。

(3)、全部命令或者全部执行,或者一个都不执行。

(4)、如果一个命令出现了异常,其他命令也不会回滚。

multi
incr a
incr b
exec
最后,Redis可以允许在一个key或多个keys上使用watch命令,可以根据这些key值是否有变化,来有条件的执行事务。这个非常有用,当你在一个事务里想获取一个key的值,并且操作这个key。如果像下面这样:

redis.multi()
current = redis.get('count')
redis.set('count’, current + 1)
redis.exec()
这样是行不通的,因为get操作,需要在exec执行后,才会提交。这时,我们使用watch命令,就可以解决这个问题:

redis.watch('count')
current = redis.get('count')
redis.multi()
redis.set('count', current + 1)
redis.exec()
如果有其他客户端修改了“count”的值,那么这个事务就会执行失败。

5、 Keys命令

Keys通过模式匹配,可以找到所有的keys。这个命令看起来很万能,但是绝不建议在生产环境使用。因为这个命令会扫描所有的key。

比如你要创建一个主机bug跟踪系统,会不会这样设计系统?

Keys: bug:account_id:bug_id
Values:异常信息字符串
那么你要查询一个主机的所有bug,你可能会习惯的执行: keys bug:123:* 命令。

但是这样,会很慢。使用hash 会是一个不错的替代方案。

hset bug:1233     1  ‘{“id”:1,”account”:123,”excepiton”:….}’
想得到某一个主机的所有bug。我们可以使用 hkeys bugs:1233.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息