Redis基础、高级特性与性能调优

内存管理优化mysql

Redis Hash是value内部为一个HashMap,若是该Map的成员数比较少,则会采用相似一维线性的紧凑格式来存储该Map, 即省去了大量指针的内存开销,这个参数控制对应在redis.conf配置文件中下面2项:redis

hash-max-zipmap-entries 64 hash-max-zipmap-value 512sql

当value这个Map内部不超过多少个成员时会采用线性紧凑格式存储,默认是64,即value内部有64个如下的成员就是使用线性紧凑存储,超过该值自动转成真正的HashMap。数据库

hash-max-zipmap-value 含义是当 value这个Map内部的每一个成员值长度不超过多少字节就会采用线性紧凑存储来节省空间。缓存

以上2个条件任意一个条件超过设置值都会转换成真正的HashMap,也就不会再节省内存了,那么这个值是否是设置的越大越好呢,答案固然是否认的,HashMap的优点就是查找和操做的时间复杂度都是O(1)的,而放弃Hash采用一维存储则是O(n)的时间复杂度,若是运维

成员数量不多,则影响不大,不然会严重影响性能,因此要权衡好这个值的设置,整体上仍是最根本的时间成本和空间成本上的权衡。性能

list-max-ziplist-value 64 list-max-ziplist-entries 512优化

list数据类型节点值大小小于多少字节会采用紧凑存储格式、list数据类型多少节点如下会采用去指针的紧凑存储格式。操作系统

内存预分配:设计

Redis内部实现没有对内存分配方面作过多的优化(对比Memcache),在必定程度上会存在内存碎片,不过大多数状况下这个不会成为Redis的性能瓶颈,不过若是在Redis内部存储的大部分数据是数值型的话,Redis内部采用了一个shared integer的 方式来省去分配内存的开销,即在系统启动时先分配一个从1~n 那么多个数值对象放在一个池子中,若是存储的数据刚好是这个数值范围内的数据,则直接从池子里取出该对象,而且经过引用计数的方式来共享,这样在系统存储 了大量数值下,也能必定程度上节省内存而且提升性能,这个参数值n的设置须要修改源代码中的一行宏定义REDIS_SHARED_INTEGERS,该值 默认是10000,能够根据本身的须要进行修改,修改后从新编译就能够了。

持久化机制:

定时快照方式(snapshot):

该持久化方式实际是在Redis内部一个定时器事件,每隔固定时间去检查当前数据发生的改变次数与时间是否知足配置的持久化触发的条件,若是知足则通 过操做系统fork调用来建立出一个子进程,这个子进程默认会与父进程共享相同的地址空间,这时就能够经过子进程来遍历整个内存来进行存储操做,而主进程 则仍然能够提供服务,当有写入时由操做系统按照内存页(page)为单位来进行copy-on-write保证父子进程之间不会互相影响。

该持久化的主要缺点是定时快照只是表明一段时间内的内存映像,因此系统重启会丢失上次快照与重启之间全部的数据。

基于语句追加方式(aof):

aof方式实际相似mysql的基于语句的binlog方式,即每条会使Redis内存数据发生改变的命令都会追加到一个log文件中,也就是说这个log文件就是Redis的持久化数据。

aof的方式的主要缺点是追加log文件可能致使体积过大,当系统重启恢复数据时若是是aof的方式则加载数据会很是慢,几十G的数据可能须要几小时才能加载完,固然这个耗时并非由于磁盘文件读取速度慢,而是因为读取的全部命令都要在内存中执行一遍。另外因为每条命令都要写log,因此使用aof的方式,Redis的读写性能也会有所降低。

能够考虑将数据保存到不一样的Redis实例中,每一个实例的内存大小在2G左右,避免将鸡蛋放到一个篮子里,既能够减小缓存失效给系统带来的影响,又能够加快数据恢复的速度,不过同时也给系统设计带来了必定的复杂性。

Redis持久化崩溃问题:

有Redis线上运维经验的人会发现Redis在物理内存使用比较多,但尚未超过实际物理内存总容量时就会发生不稳定甚至崩溃的 问题,有人认为是基于快照方式持久化的fork系统调用形成内存占用加倍而致使的,这种观点是不许确的,由于fork 调用的copy-on-write机制是基于操做系统页这个单位的,也就是只有有写入的脏页会被复制,可是通常你的系统不会在短期内全部的页都发生了写 入而致使复制,那么是什么缘由致使Redis崩溃的呢?

答案是Redis的持久化使用了Buffer IO造 成的,所谓Buffer IO是指Redis对持久化文件的写入和读取操做都会使用物理内存的Page Cache,而大多数数据库系统会使用Direct IO来绕过这层Page Cache并自行维护一个数据的Cache,而当Redis的持久化文件过大(尤为是快照文件),并对其进行读写时,磁盘文件中的数据都会被加载到物理内 存中做为操做系统对该文件的一层Cache,而这层Cache的数据与Redis内存中管理的数据实际是重复存储的,虽然内核在物理内存紧张时会作 Page Cache的剔除工做,但内核极可能认为某块Page Cache更重要,而让你的进程开始Swap ,这时你的系统就会开始出现不稳定或者崩溃了。咱们的经验是当你的Redis物理内存使用超过内存总容量的3/5时就会开始比较危险了。

总结:

一、根据业务须要选择合适的数据类型,并为不一样的应用场景设置相应的紧凑存储参数。

二、当业务场景不须要数据持久化时,关闭全部的持久化方式能够得到最佳的性能以及最大的内存使用量。

三、若是须要使用持久化,根据是否能够容忍重启丢失部分数据在快照方式与语句追加方式之间选择其一,不要使用虚拟内存以及diskstore方式。

四、不要让你的Redis所在机器物理内存使用超过实际内存总量的3/5。

redis.conf中的maxmemory选项,该选项是告诉Redis当使用了多少物理内存后就开始拒绝后续的写入请求,该参数能很好的保护好你的Redis不会由于使用了过多的物理内存而致使swap,最终严重影响性能甚至崩溃。

redis.conf文件中 vm-enabled 为 no

相关文章
相关标签/搜索