首页 » NoSQL » Redis需特别注意的场景

Redis需特别注意的场景

2016-05-25 16:41:30阅读(215)

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.

最新发布

CentOS专题

关于本站

5ibc.net旗下博客站精品博文小部分原创、大部分从互联网收集整理。尊重作者版权、传播精品博文,让更多编程爱好者知晓!

小提示

按 Ctrl+D 键,
把本文加入收藏夹