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,类似下面的。
一个比较好的解决办法,应该使用Redis的hash。
get users:123
如果想通过email找到用户,需要执行两个命令:
Redis还支持管道。通常情况下,客户端每个请求命令发出后,会阻塞,等待redis服务处理,Redis处理完后请求命令后会将结构通过响应报文返回给client。利用管道模式,我们可以从客户端发出多条命令,不需要等待单条命令的返回,Redis服务端会将多条命令的处理结果打包一起返回给客户端。这减少网络开销,性能得到显著提升。 利用Pipeline打包命令发送,Redis必须在处理完所有命令前线缓存起所有命令的处理结果。打包的命令越多,缓存消耗内存也越多。所以并不是打包的命令越多越好。具体多少合适需要根据情况测试。下面是Jedis客户端利用Pipeline的一段代码。
Redis的每个命令都是原子的,包括那些需要多步操作的命令(incr,getset,setnx)。
Redis提供了事务机制,可以把多个命令作为一个原子性操作组执行。步骤很简单,先执行multi命令,跟着执行你的命令,最后可以执行exec命令提交所有操作,也可以执行discard命令放弃所有操作。先看看Redis对于事务的都有哪些要素:
(1)、全部命令会被顺序执行。
(2)、全部命令执行不会被打断。
(3)、全部命令或者全部执行,或者一个都不执行。
(4)、如果一个命令出现了异常,其他命令也不会回滚。
5、 Keys命令
Keys通过模式匹配,可以找到所有的keys。这个命令看起来很万能,但是绝不建议在生产环境使用。因为这个命令会扫描所有的key。
比如你要创建一个主机bug跟踪系统,会不会这样设计系统?
但是这样,会很慢。使用hash 会是一个不错的替代方案。
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.
相关文章推荐
- redis安装问题小结
- 使用 Redis 和 Python 构建一个共享单车的应用程序
- Redis偶发连接失败案例实战记录
- Redis中实现查找某个值的范围
- win 7 安装redis服务【笔记】
- redis的hGetAll函数的性能问题(记Redis那坑人的HGETALL)
- Redis和Memcached的区别详解
- 分割超大Redis数据库例子
- Redis总结笔记(一):安装和常用命令
- Redis sort 排序命令详解
- 用Redis实现微博关注关系
- Redis实现信息已读未读状态提示
- redis中修改配置文件中的端口号 密码方法
- 在Ruby on Rails上使用Redis Store的方法
- SQL Server误区30日谈 第1天 正在运行的事务在服务器故障转移后继续执行
- 浅析SQL Server中包含事务的存储过程
- Mysql中的事务是什么如何使用
- MySql的事务使用与示例详解
- Redis和Memcache的区别总结
- C#分布式事务的超时处理实例分析