目录
1定义
2作者
3性能
4支持语言
|
|
|
|
|
5数据模型
6数据结构
1
2
3
4
5
6
|
typedefchar*sds;
structsdshdr{
longlen;
longfree;
charbuf[];
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//list迭代器
typedefstructlistIter{
listNode*next;
intdirection;
}listIter;
//list数据结构
typedefstructlist{
listNode*head;
listNode*tail;
void
*(*dup)(
void
*ptr);
void
(*
free
)(
void
*ptr);
int
(*match)(
void
*ptr,
void
*key);
unsignedintlen;
listIteriter;
}list;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
//dict中的元素项
typedefstructdictEntry{
void
*key;
void
*val;
structdictEntry*next;
}dictEntry;
//dict相关配置函数
typedefstructdictType{
unsignedint(*hashFunction)(constvoid*key);
void
*(*keyDup)(
void
*privdata,constvoid*key);
void
*(*valDup)(
void
*privdata,constvoid*obj);
int
(*keyCompare)(
void
*privdata,constvoid*key1,constvoid*key2);
void
(*keyDestructor)(
void
*privdata,
void
*key);
void
(*valDestructor)(
void
*privdata,
void
*obj);
}dictType;
//dict定义
typedefstructdict{
dictEntry**table;
dictType*type;
unsignedlongsize;
unsignedlongsizemask;
unsignedlongused;
void
*privdata;
}dict;
//dict迭代器
typedefstructdictIterator{
dict*ht;
intindex;
dictEntry*entry,*nextEntry;
}dictIterator;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
typedefstructzskiplistNode{
structzskiplistNode**forward;
structzskiplistNode*backward;
doublescore;
robj*obj;
}zskiplistNode;
typedefstructzskiplist{
structzskiplistNode*header,*tail;
unsignedlonglength;
intlevel;
}zskiplist;
typedefstructzset{
dict*dict;
zskiplist*zsl;
}zset;
|
7常用命令
8存储
9安装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
daemonizeyes
pidfile/usr/local/redis/var/redis.pid
port6379
timeout300
logleveldebug
logfile/usr/local/redis/var/redis.
log
databases16
save9001
save30010
save6010000
rdbcompressionyes
dbfilenamedump.rdb
dir/usr/local/redis/var/
appendonlyno
appendfsyncalways
glueoutputbufyes
shareobjectsno
shareobjectspoolsize1024
|
首先最重要的一点是不要开启Redis的VM选项,即虚拟内存功能,这个本来是作为Redis存储超出物理内存数据的一种数据在内存与磁盘换入换出的一个持久化策略,但是其内存管理成本也非常的高,并且我们后续会分析此种持久化策略并不成熟,所以要关闭VM功能,请检查你的redis.conf文件中 vm-enabled 为 no。
其次最好设置下redis.conf中的maxmemory选项,该选项是告诉Redis当使用了多少物理内存后就开始拒绝后续的写入请求,该参数能很好的保护好你的Redis不会因为使用了过多的物理内存而导致swap,最终严重影响性能甚至崩溃。
另外Redis为不同数据类型分别提供了一组参数来控制内存使用,我们在前面详细分析过Redis Hash是value内部为一个HashMap,如果该Map的成员数比较少,则会采用类似一维线性的紧凑格式来存储该Map, 即省去了大量指针的内存开销,这个参数控制对应在redis.conf配置文件中下面2项:
-
hash-max-zipmap-entries 64
-
hash-max-zipmap-value 512
-
hash-max-zipmap-entries
hash-max-zipmap-value 含义是当 value这个Map内部的每个成员值长度不超过多少字节就会采用线性紧凑存储来节省空间。
以上2个条件任意一个条件超过设置值都会转换成真正的HashMap,也就不会再节省内存了,那么这个值是不是设置的越大越好呢,答案当然是否定的,HashMap的优势就是查找和操作的时间复杂度都是O(1)的,而放弃Hash采用一维存储则是O(n)的时间复杂度,如果
成员数量很少,则影响不大,否则会严重影响性能,所以要权衡好这个值的设置,总体上还是最根本的时间成本和空间成本上的权衡。
说明:list数据类型多少节点以下会采用去指针的紧凑存储格式。
list-max-ziplist-value 64
说明:list数据类型节点值大小小于多少字节会采用紧凑存储格式。
set-max-intset-entries 512
说明:set数据类型内部数据如果全部是数值型,且包含多少节点以下会采用紧凑格式存储。
最后想说的是Redis内部实现没有对内存分配方面做过多的优化,在一定程度上会存在内存碎片,不过大多数情况下这个不会成为Redis的性能瓶颈,不过如果在Redis内部存储的大部分数据是数值型的话,Redis内部采用了一个shared integer的方式来省去分配内存的开销,即在系统启动时先分配一个从1~n 那么多个数值对象放在一个池子中,如果存储的数据恰好是这个数值范围内的数据,则直接从池子里取出该对象,并且通过引用计数的方式来共享,这样在系统存储了大量数值下,也能一定程度上节省内存并且提高性能,这个参数值n的设置需要修改源代码中的一行宏定义REDIS_SHARED_INTEGERS,该值默认是10000,可以根据自己的需要进行修改,修改后重新编译就可以了。
另外redis 的6种过期策略redis 中的默认的过期策略是volatile-lru 。设置方式
config set maxmemory-policy volatile-lru
maxmemory-policy 六种方式
volatile-lru:只对设置了过期时间的key进行LRU(默认值)
allkeys-lru : 是从所有key里 删除 不经常使用的key
volatile-random:随机删除即将过期key
allkeys-random:随机删除
volatile-ttl : 删除即将过期的
noeviction : 永不过期,返回错误
maxmemory-samples 3 是说每次进行淘汰的时候 会随机抽取3个key 从里面淘汰最不经常使用的(默认选项)
10版本发布
-
参考资料
-
-
1. 超高性能 key-value 数据库 Redis .开源社区网 [引用日期2012-09-8] .
-
2. 超强、超详细Redis数据库入门教程 .藏宝阁 .2014-12-06 [引用日期2014-12-23] .
-
3. Redis 2.4.16 小更新版本 NoSQL .开源社区网 [引用日期2012-09-25] .
-
4. Redis 2.4.17 小更新版本 NoSQL .开源社区网 [引用日期2012-09-25] .
-
5. Redis 2.6.13 发布,高性能K/V服务器 .Linux公社 [引用日期2013-06-19] .
-
6. Redis 2.8 release notes .git hub [引用日期2013-11-26] .
-
7. Redis 3.0.0 RC3 发布,高性能 K/V 数据库 .Redis 3.0.0 RC3 发布 [引用日期2015-02-11] .
-
Redis
目录
1定义
2作者
3性能
4支持语言
|
|
|
|
|
5数据模型
6数据结构
1
2
3
4
5
6
|
typedefchar*sds;
structsdshdr{
longlen;
longfree;
charbuf[];
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//list迭代器
typedefstructlistIter{
listNode*next;
intdirection;
}listIter;
//list数据结构
typedefstructlist{
listNode*head;
listNode*tail;
void
*(*dup)(
void
*ptr);
void
(*
free
)(
void
*ptr);
int
(*match)(
void
*ptr,
void
*key);
unsignedintlen;
listIteriter;
}list;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
//dict中的元素项
typedefstructdictEntry{
void
*key;
void
*val;
structdictEntry*next;
}dictEntry;
//dict相关配置函数
typedefstructdictType{
unsignedint(*hashFunction)(constvoid*key);
void
*(*keyDup)(
void
*privdata,constvoid*key);
void
*(*valDup)(
void
*privdata,constvoid*obj);
int
(*keyCompare)(
void
*privdata,constvoid*key1,constvoid*key2);
void
(*keyDestructor)(
void
*privdata,
void
*key);
void
(*valDestructor)(
void
*privdata,
void
*obj);
}dictType;
//dict定义
typedefstructdict{
dictEntry**table;
dictType*type;
unsignedlongsize;
unsignedlongsizemask;
unsignedlongused;
void
*privdata;
}dict;
//dict迭代器
typedefstructdictIterator{
dict*ht;
intindex;
dictEntry*entry,*nextEntry;
}dictIterator;
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
typedefstructzskiplistNode{
structzskiplistNode**forward;
structzskiplistNode*backward;
doublescore;
robj*obj;
}zskiplistNode;
typedefstructzskiplist{
structzskiplistNode*header,*tail;
unsignedlonglength;
intlevel;
}zskiplist;
typedefstructzset{
dict*dict;
zskiplist*zsl;
}zset;
|
7常用命令
8存储
9安装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
daemonizeyes
pidfile/usr/local/redis/var/redis.pid
port6379
timeout300
logleveldebug
logfile/usr/local/redis/var/redis.
log
databases16
save9001
save30010
save6010000
rdbcompressionyes
dbfilenamedump.rdb
dir/usr/local/redis/var/
appendonlyno
appendfsyncalways
glueoutputbufyes
shareobjectsno
shareobjectspoolsize1024
|
首先最重要的一点是不要开启Redis的VM选项,即虚拟内存功能,这个本来是作为Redis存储超出物理内存数据的一种数据在内存与磁盘换入换出的一个持久化策略,但是其内存管理成本也非常的高,并且我们后续会分析此种持久化策略并不成熟,所以要关闭VM功能,请检查你的redis.conf文件中 vm-enabled 为 no。
其次最好设置下redis.conf中的maxmemory选项,该选项是告诉Redis当使用了多少物理内存后就开始拒绝后续的写入请求,该参数能很好的保护好你的Redis不会因为使用了过多的物理内存而导致swap,最终严重影响性能甚至崩溃。
另外Redis为不同数据类型分别提供了一组参数来控制内存使用,我们在前面详细分析过Redis Hash是value内部为一个HashMap,如果该Map的成员数比较少,则会采用类似一维线性的紧凑格式来存储该Map, 即省去了大量指针的内存开销,这个参数控制对应在redis.conf配置文件中下面2项:
-
hash-max-zipmap-entries 64
-
hash-max-zipmap-value 512
-
hash-max-zipmap-entries
hash-max-zipmap-value 含义是当 value这个Map内部的每个成员值长度不超过多少字节就会采用线性紧凑存储来节省空间。
以上2个条件任意一个条件超过设置值都会转换成真正的HashMap,也就不会再节省内存了,那么这个值是不是设置的越大越好呢,答案当然是否定的,HashMap的优势就是查找和操作的时间复杂度都是O(1)的,而放弃Hash采用一维存储则是O(n)的时间复杂度,如果
成员数量很少,则影响不大,否则会严重影响性能,所以要权衡好这个值的设置,总体上还是最根本的时间成本和空间成本上的权衡。
说明:list数据类型多少节点以下会采用去指针的紧凑存储格式。
list-max-ziplist-value 64
说明:list数据类型节点值大小小于多少字节会采用紧凑存储格式。
set-max-intset-entries 512
说明:set数据类型内部数据如果全部是数值型,且包含多少节点以下会采用紧凑格式存储。
最后想说的是Redis内部实现没有对内存分配方面做过多的优化,在一定程度上会存在内存碎片,不过大多数情况下这个不会成为Redis的性能瓶颈,不过如果在Redis内部存储的大部分数据是数值型的话,Redis内部采用了一个shared integer的方式来省去分配内存的开销,即在系统启动时先分配一个从1~n 那么多个数值对象放在一个池子中,如果存储的数据恰好是这个数值范围内的数据,则直接从池子里取出该对象,并且通过引用计数的方式来共享,这样在系统存储了大量数值下,也能一定程度上节省内存并且提高性能,这个参数值n的设置需要修改源代码中的一行宏定义REDIS_SHARED_INTEGERS,该值默认是10000,可以根据自己的需要进行修改,修改后重新编译就可以了。
另外redis 的6种过期策略redis 中的默认的过期策略是volatile-lru 。设置方式
config set maxmemory-policy volatile-lru
maxmemory-policy 六种方式
volatile-lru:只对设置了过期时间的key进行LRU(默认值)
allkeys-lru : 是从所有key里 删除 不经常使用的key
volatile-random:随机删除即将过期key
allkeys-random:随机删除
volatile-ttl : 删除即将过期的
noeviction : 永不过期,返回错误
maxmemory-samples 3 是说每次进行淘汰的时候 会随机抽取3个key 从里面淘汰最不经常使用的(默认选项)
10版本发布
-
参考资料
-
-
1. 超高性能 key-value 数据库 Redis .开源社区网 [引用日期2012-09-8] .
-
2. 超强、超详细Redis数据库入门教程 .藏宝阁 .2014-12-06 [引用日期2014-12-23] .
-
3. Redis 2.4.16 小更新版本 NoSQL .开源社区网 [引用日期2012-09-25] .
-
4. Redis 2.4.17 小更新版本 NoSQL .开源社区网 [引用日期2012-09-25] .
-
5. Redis 2.6.13 发布,高性能K/V服务器 .Linux公社 [引用日期2013-06-19] .
-
6. Redis 2.8 release notes .git hub [引用日期2013-11-26] .
-
7. Redis 3.0.0 RC3 发布,高性能 K/V 数据库 .Redis 3.0.0 RC3 发布 [引用日期2015-02-11] .
-