首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 互联网 >

Redis细节累积

2012-07-25 
Redis细节积累Redis细节积累???????????????????????????? ?? 本文主要说明一些redis优点和缺点以免网站架

Redis细节积累

Redis细节积累

?

??????????????????????????? ?? 本文主要说明一些redis优点和缺点以免网站架构时乱用

一、优点

?

key/value存储支持丰富的数据结构操作(list、set、map等操作)支持批量的操作,减少网络的开销支持replication机制,弥补了aof、snapshot性能上不足,达到了数据可持久化支持虚拟内存,没有开来操作系统的虚拟内存管理,而是自己开发封装,具体原因参考:http://blog.nosqlfan.com/html/868.html?ref=rediszt

?

二、缺点

?

?

是基于内存管理,也就是自己申请内存管理数据,当进程重启或者挂了就会丢失数据,所以可以考虑使用内存文件系统,只要系统部重启数据不会丢失,细节参见:http://blog.nosqlfan.com/html/3638.html关于使用hashtable的时候,当数据达到zimap数据的临界值的时候,有一次rehash的扩容,这个时间点会有性能上的缺陷,只是个人看源代码的想法,欢迎指教复制机制的缺陷:没有像MySQL那样有复制位置的概念,即无增量复制,这会给整个集群搭建带来非常多的问题。详细见:http://blog.nosqlfan.com/html/3153.html?ref=rediszt

三、redis复制缺陷的解决方案

?

主动复制避开Redis复制缺陷

?????? 我们可以采用主动复制的方式来搭建我们的集群环境,所谓主动复制是指由业务端或者通过代理中间件对Redis存储的数据进行双写或多写,通过数据的多份存储来达到与复制相同的目的。但是会造成数据一致性问题,这样需要看项目的应用场景是否对数据一致性要求高不高

?

通过presharding进行Redis在线扩容

???? resharding的方案来解决动态扩容和数据分区的问题,实际就是在同一台机器上部署多个Redis实例的方式,当容量不够时将多个实例拆分到不同的机器上,这样实际就达到了扩容的效果。但是实际还是依赖redis的复制功能,所以做这个拆分的过程最好选择为业务访问低峰时段进行。

Redis复制的改进

?? 首先写Redis的AOF文件,并对这个AOF文件按文件大小进行自动分割滚动,同时关闭Redis的Rewrite命令,然后会在业务低峰时间进行内存快照存储,并把当前的AOF文件位置一起写入到快照文件中,这样我们可以使快照文件与AOF文件的位置保持一致性,这样我们得到了系统某一时刻的内存快照,并且同时也能知道这一时刻对应的AOF文件的位置,那么当从库发送同步命令时,我们首先会把快照文件发送给从库,然后从库会取出该快照文件中存储的AOF文件位置,并将该位置发给主库,主库会随后发送该位置之后的所有命令,以后的复制就都是这个位置之后的增量信息了。

Redis与MySQL的结合

四、内存优化

?

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:

list-max-ziplist-entries 512set-max-intset-entries 512 

不过如果在Redis内部存储的大部分数据是数值型的话,Redis内部采用了一个shared integer的方式来省去分配内存的开销,即在系统启动时先分配一个从1~n 那么多个数值对象放在一个池子中,如果存储的数据恰好是这个数值范围内的数据,则直接从池子里取出该对象,并且通过引用计数的方式来共享,这样在系统存储了大量数值下,也能一定程度上节省内存并且提高性能,这个参数值n的设置需要修改源代码中的一行宏定义REDIS_SHARED_INTEGERS,该值默认是10000,可以根据自己的需要进行修改,修改后重新编译就可以了。

?

有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时就会开始比较危险了。

?

?

?

?

?

?

热点排行