Redis简述
html
Redis 是彻底开源免费的,遵照BSD协议,先进的key - value持久化产品。它一般被称为数据结构服务器,由于值(value)能够是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。
redis
redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类keyvalue存储的不足,在部 分场合能够对关系数据库起到很好的补充做用。它提供了Python,Ruby,Erlang,PHP客户端,使用很方便。问题是这个项目还很新,可能还不足够稳定,并且没有在实际的一些大型系统应用的实例。此外,缺少mc中批量get也是比较大的问题,始终批量获取跟屡次获取的网络开销是不同的。
性能测试结果:
SET操做每秒钟 110000 次,GET操做每秒钟 81000 次,服务器配置以下:
Linux 2.6, Xeon X3320 2.5Ghz.
stackoverflow 网站使用 Redis 作为缓存服务器。数据库
安装过程:
Redis是一种高级key-value数据库。它跟memcached相似,不过数据能够持久化,并且支持的数据类型很丰富。有字符串,链表,集 合和有序集合。支持在服务器端计算集合的并,交和补集(difference)等,还支持多种排序功能。因此Redis也能够被当作是一个数据结构服务 器。数组
Redis的全部数据都是保存在内存中,而后不按期的经过异步方式保存到磁盘上(这称为“半持久化模式”);也能够把每一次数据变化都写入到一个append only file(aof)里面(这称为“全持久化模式”)。缓存
一、redis 中的每个数据库,都由一个 redisDb 的结构存储。其中,redisDb.id 存储着 redis 数据库以整数表示的号码。redisDb.dict 存储着该库全部的键值对数据。redisDb.expires 保存着每个键的过时时间。 二、当redis 服务器初始化时,会预先分配 16 个数据库(该数量能够经过配置文件配置),全部数据库保存到结构 redisServer 的一个成员 redisServer.db 数组中。当咱们选择数据库 select number 时,程序直接经过 redisServer.db[number] 来切换数据库。有时候当程序须要知道本身是在哪一个数据库时,直接读取 redisDb.id 便可。 三、既然咱们知道一个数据库的全部键值都存储在redisDb.dict中,那么咱们要知道若是找到key的位置,就有必要了解一下dict 的结构了: typedef struct dict { // 特定于类型的处理函数 dictType *type; // 类型处理函数的私有数据 void *privdata; // 哈希表(2个) dictht ht[2]; // 记录 rehash 进度的标志,值为-1 表示 rehash 未进行 int rehashidx; // 当前正在运做的安全迭代器数量 int iterators; } dict; 由上述的结构能够看出,redis 的字典使用哈希表做为其底层实现。dict 类型使用的两个指向哈希表的指针,其中 0 号哈希表(ht[0])主要用于存储数据库的全部键值,而1号哈希表主要用于程序对 0 号哈希表进行 rehash 时使用,rehash 通常是在添加新值时会触发,这里不作过多的赘述。因此redis 中查找一个key,其实就是对进行该dict 结构中的 ht[0] 进行查找操做。 四、既然是哈希,那么咱们知道就会有哈希碰撞,那么当多个键哈希以后为同一个值怎么办呢?redis采起链表的方式来存储多个哈希碰撞的键。也就是说,当根据key的哈希值找到该列表后,若是列表的长度大于1,那么咱们须要遍历该链表来找到咱们所查找的key。固然,通常状况下链表长度都为是1,因此时间复杂度可看做o(1)。
redis下,数据库是由一个整数索引标识,而不是由一个数据库名称。默认状况下,一个客户端链接到数据库0。redis配置文件中下面的参数来控制数据库总数:
安全
默认状况下是16个。修改redis.conf下的databases指令:服务器
databases 16网络
能够经过下面的命令来切换到不一样的数据库下
数据结构
select 2
app
Redis最为经常使用的数据类型主要有如下五种:
●String
●Hash
●List
●Set
●Sorted set
set,get,decr,incr,mget
hget,hset,hgetall
lpush,rpush,lpop,rpop,lrange
sadd,spop,smembers,sunion
zadd,zrange,zrem,zcard
Redis的持久化机制
Redis因为支持很是丰富的内存数据结构类型,如何把这些复杂的内存组织方式持久化到磁盘上是一个难题,因此Redis的持久化方式与传统数据库的方式有比较多的差异,Redis一共支持四种持久化方式,分别是:
●定时快照方式(snapshot)
●基于语句追加文件的方式(aof)
●虚拟内存(vm)
●Diskstore方式
常用内存优化手段与参数
经过咱们上面的一些实现上的分析能够看出redis实际上的内存管理成本很是高,即占用了过多的内存,做者对这点也非常清楚,因此提供了一系列的参数和手段来控制和节省内存,咱们分别来讨论下。
首先最重要的一点是不要开启Redis的VM选项,即虚拟内存功能,这个原本是做为Redis存储超出物理内存数据的一种数据在内存与磁盘换入换出的一个持久化策略,可是其内存管理成本也很是的高,而且咱们后续会分析此种持久化策略并不成熟,因此要关闭VM功能,请检查你的redis.conf文件中vm-enabled 为 no。
其次最好设置下redis.conf中的maxmemory选项,该选项是告诉Redis当使用了多少物理内存后就开始拒绝后续的写入请求,该参数能很好的保护好你的Redis不会由于使用了过多的物理内存而致使swap,最终严重影响性能甚至崩溃。
另外Redis为不一样数据类型分别提供了一组参数来控制内存使用,咱们在前面详细分析过RedisHash是value内部为一个HashMap,若是该Map的成员数比较少,则会采用相似一维线性的紧凑格式来存储该Map,即省去了大量指针的内存开销,这个参数控制对应在redis.conf配置文件中下面2项:
hash-max-zipmap-entries 64
hash-max-zipmap-value 512
hash-max-zipmap-entries
含义是当value这个Map内部不超过多少个成员时会采用线性紧凑格式存储,默认是64,即value内部有64个如下的成员就是使用线性紧凑存储,超过该值自动转成真正的HashMap。
hash-max-zipmap-value 含义是当value这个Map内部的每一个成员值长度不超过多少字节就会采用线性紧凑存储来节省空间。
以上2个条件任意一个条件超过设置值都会转换成真正的HashMap,也就不会再节省内存了,那么这个值是否是设置的越大越好呢,答案固然是否认的,HashMap的优点就是查找和操做的时间复杂度都是O(1)的,而放弃Hash采用一维存储则是O(n)的时间复杂度,若是
成员数量不多,则影响不大,不然会严重影响性能,因此要权衡好这个值的设置,整体上仍是最根本的时间成本和空间成本上的权衡。
一样相似的参数还有:
list-max-ziplist-entries 512
说明:list数据类型多少节点如下会采用去指针的紧凑存储格式。
list-max-ziplist-value 64
说明:list数据类型节点值大小小于多少字节会采用紧凑存储格式。
set-max-intset-entries 512
说明:set数据类型内部数据若是所有是数值型,且包含多少节点如下会采用紧凑格式存储。
最后想说的是Redis内部实现没有对内存分配方面作过多的优化,在必定程度上会存在内存碎片,不过大多数状况下这个不会成为Redis的性能瓶颈,不过若是在Redis内部存储的大部分数据是数值型的话,Redis内部采用了一个sharedinteger的方式来省去分配内存的开销,即在系统启动时先分配一个从1~n那么多个数值对象放在一个池子中,若是存储的数据刚好是这个数值范围内的数据,则直接从池子里取出该对象,而且经过引用计数的方式来共享,这样在系统存储了大量数值下,也能必定程度上节省内存而且提升性能,这个参数值n的设置须要修改源代码中的一行宏定义REDIS_SHARED_INTEGERS,该值默认是10000,能够根据本身的须要进行修改,修改后从新编译就能够了。
总结:
1.根据业务须要选择合适的数据类型,并为不一样的应用场景设置相应的紧凑存储参数。
2.当业务场景不须要数据持久化时,关闭全部的持久化方式能够得到最佳的性能以及最大的内存使用量。
3.若是须要使用持久化,根据是否能够容忍重启丢失部分数据在快照方式与语句追加方式之间选择其一,不要使用虚拟内存以及diskstore方式。
4.不要让你的Redis所在机器物理内存使用超过实际内存总量的3/5。
Redis Desktop Manager
Redis Desktop Manager 是一个快速、简单、支持跨平台的 Redis 桌面管理工具,基于 Qt 5 开发,支持经过 SSH Tunnel 链接。