Redis 关键 点

来源:互联网 发布:未注册网络什么意思 编辑:程序博客网 时间:2024/06/06 09:29

一    虚拟内存(适用于value比key大的情况)

 1.Redis虚拟内存简介

      首先说明下redis的虚拟内存与操作系统虚拟内存不是一码事,但是思路和目的都是相同的。就是暂时把不经常访问的数据从内存交换到磁盘中,从而腾出宝贵的内存空间。对于redis这样的内存数据库,内存总是不够用的。除了可以将数据分割到多个redis服务器以外。另外的能够提高数据库容量的办法就是使用虚拟内存技术把那些不经常访问的数据交换到磁盘上。如果我们存储的数据总是有少部分数据被经常访问,大部分数据很少被访问,对于网站来说确实总是只有少量用户经常活跃。当少量数据被经常访问时,使用虚拟内存不但能提高单台redis数据库服务器的容量,而且也不会对性能造成太多影响。
      redis没有使用操作系统提供的虚拟内存机制而是自己在用户态实现了自己的虚拟内存机制。
主要的理由有以下两点:
      1.操作系统的虚拟内存是以4k/页为最小单位进行交换的。而redis的大多数对象都远小于4k,所以一个操作系统页上可能有多个redis对象。另外redis的集合对象类型如list,set可能存在于多个操作系统页上。最终可能造成只有10%的key被经常访问,但是所有操作系统页都会被操作系统认为是活跃的,这样只有内存真正耗尽时操作系统才会进行页的交换。
     2.相比操作系统的交换方式。redis可以将被交换到磁盘的对象进行压缩,保存到磁盘的对象可以去除指针和对象元数据信息。一般压缩后的对象会比内存中的对象小10倍。这样redis的虚拟内存会比操作系统的虚拟内存少做很多IO操作。

   2.Redis虚拟内存相关配置

vm-enabledyes#开启虚拟内存功能

vm-swap-file/tmp/redis.swap#交换出来value保存的文件路径/tmp/redis.swap

vm-max-memory268435456   

#redis使用的最大内存上限(256MB),超过上限后redis开始交换value到磁盘swap文件中。建议设置为系统空闲内存的60%-80%

vm-page-size32#每个redis页的大小32个字节

vm-pages134217728#最多在文件中使用多少个页,交换文件的大小=(vm-page-size*vm-pages)4GB

vm-max-threads8#用于执行value对象换入换出的工作线程数量。0表示不使用工作线程(详情后面介绍)


      redis的虚拟内存在设计上为了保证key的查询速度,只会将value交换到swap文件中。如果是由于太多key很小的value造成的内存问题,那么redis的虚拟内存并不能解决问题。和操作系统一样redis也是按页来交换对象的。redis规定同一个页只能保存一个对象。但是一个对象可以保存在多个页中。在redis使用的内存没超过vm-max-memory之前是不会交换任何value的。当超过最大内存限制后,redis会选择把较老的对象交换到swap文件中去。如果两个对象一样老会优先交换比较大的对象,精确的交换计算公式swappability=age*log(size_in_memory)。对于vm-page-size的设置应该根据自己应用将页的大小设置为可以容纳大多数对象的尺寸。太大了会浪费磁盘空间,太小了会造成交换文件出现过多碎片。对于交换文件中的每个页,redis会在内存中用一个1bit值来对应记录页的空闲状态。所以像上面配置中页数量(vm-pages134217728)会占用16MB内存用来记录页的空闲状态。

vm-max-threads表示用做交换任务的工作线程数量。如果大于0推荐设为服务器的cpu的核心数。如果是0则交换过程在主线程进行。

3.redis虚拟内存工作方式简介

1.当vm-max-threads设为0时(阻塞方式)

换出

主线程定期检查发现内存超出最大上限后,会直接以阻塞的方式,将选中的对象保存到swap文件中,并释放对象占用的内存空间,此过程会一直重复直到下面条件满足

1.内存使用降到最大限制以下

2.swap文件满了。

3.几乎全部的对象都被交换到磁盘了

换入

当有客户端请求已经被换出的value时,主线程会以阻塞的方式从swap文件中加载对应的value对象,加载时此时会阻塞所有客户端。然后处理该客户端的请求

2.当vm-max-threads大于0时(工作线程方式)

换出
        当主线程检测到使用内存超过最大上限,会将选中要交换的对象信息放到一个队列中交给工作线程后台处理,主线程会继续处理客户端请求。
换入
      如果有客户端请求的key已经被换出了,主线程会先阻塞发出命令的客户端,然后将加载对象的信息放到一个队列中,让工作线程去加载。加载完毕后工作线程通知主线程。主线程再执行客户端的命令。这种方式只阻塞请求的value是已经被换出key的客户端。

    总的来说阻塞方式的性能会好一些,因为不需要线程同步、创建线程和恢复被阻塞的客户端等开销。但是也相应的牺牲了响应性。工作线程方式主线程不会阻塞在磁盘IO上,所以响应性更好。如果我们的应用不太经常发生换入换出,而且也不太在意有点延迟的话推荐使用阻塞方式。

关于redis虚拟内存更详细介绍可以参考下面链接http://redis.io/topics/internals-vm

二 redis支持简单事务

    

三  实践关键注意

     

 四  水平分区,Sharding

  • 其实,大内存加上垂直分区也够了,不一定非要沙丁一把。
  • Jedis支持在客户端做分区,局限是不能动态re-sharding, 有分区的master倒了,不能减少分区必须用slave顶上。要增加分区的话,呃…..
  • antire在博客里提到了Twemproxy,一个Twitter写的Proxy,但它在发现节点倒掉后,只会重新计算一致性哈希环,把数据存到别的master去,而不是集成Sentinel指向新由slave升级的master,像Memcached一样的做法也只适合做Cache的场景。

Redis-Cluster是今年工作重点,支持automatic re-sharding, 采用和Hazelcast类似的算法,总共有N个分区(eg.N=1024),每台Server负责若干个分区。

  • 在客户端先hash出key 属于哪个分区,随便发给一台server,server会告诉它真正哪个Server负责这个分区,缓存下来,下次还有该分区的请求就直接发到地儿了。
  • Re-sharding时,会将某些分区的数据移到新的Server上,完成后各Server周知分区<->Server映射的变化,因为分区数量有限,所以通讯量不大。 在迁移过程中,客户端缓存的依然是旧的分区映射信息,原server对于已经迁移走的数据的get请求,会返回一个临时转向的应答,客户端先不会更新Cache。等迁移完成了,就会像前面那样返回一条永久转向信息,客户端更新Cache,以后就都去新server了。

五 高可用性

高可用性关乎系统出错时到底会丢失多少数据,多久不能服务。要综合考虑持久化,Master-Slave复制及Fail-Over配置,以及具体Crash情形,比如Master死了,但Slave没死。或者只是Redis死了,操作系统没死等等。

六  Redis适用场景

   


 



0 0