数据平台前端缓存技术方案Memcached-Redis.v1.0

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

数据平台前端缓存技术方案(M/R)version:v1.01缓存Memcached(M)1.1M的概念M是高性能的分布式内存缓存服务器,协议简单。通过缓存数据库的查询结果,减少数据库访问次数,提高动态Web应用的速度和扩展性。M支持下述语言1.2M的设计1.2.1M的机制守护进程机制:UNIXDaemon;Socket事件处理机制:非阻塞、Libevent异步事件处理、Epoll/Kqueue;内存管理机制:Slab内存分配、LRU对象清除、Hash快速检索Item。内存管理中,Slab中分成小单位Chunk,Chunk中存有实际数据Item。下述是M的Slab内存结构图和分配实例图。Slab内存结构图Slab内存分配实例图Slab计算占用内存图Item数据存储格式图1.2.2M的架构设计M的设计遵从原则是,首次访问从RDBMS中取得数据,按一定规则保存到M后,第二次访问从M中取得数据显示到浏览器页面中。M架构层次图M的服务端并没有分布式功能,各个服务器之间没有互相通信以共享信息。M的分布式完全取决于客户端的实现,如下图所示。M使用说明图如需要在M中保存键名为“tokyo”的数据时,通过客户端应用程序的算法,根据Key来决定选择哪个服务器节点进行存储。服务器选定之后,命令其保存键名“tokyo”和键值“data”。Set实例图如需要在M中获取键名为“tokyo”的数据时。把键名“tokyo”传给客户端函数库,通过和数据保存相同的算法,根据Key选择服务器节点。只要算法一致,就能选对服务器,发送命令取得键值“data”。Get实例图1.3M的客户端算法1.3.1余数分散根据服务器台数的余数进行分散,求得Key的整数Hash值H,除以服务器的台数N,由余数指向选中服务器,即H%N。算法的数据分散性比较优秀,但不足的是当添加/移除服务器时(包括服务器Down机事件),缓存重组的代价相当大。因为添加/移除服务器后,余数必定发生改变,客户端在获取数据时,就无法通过算法获取和保存时相同的服务器,严重影响了缓存的命中率。大部分负载会在事件发生的同时,增大数据库的压力。1.3.2一致性哈希一致性哈希算法,ConsistentHashing是一种分布式算法,常用于负载均衡。M客户端选择这种算法,解决将Key-Value均匀分配到众多M服务器上的问题。它可以取代传统的取模操作,解决了上述取模操作无法应对增删M服务器所遇到的问题。一致性哈希算法图一致性哈希算法增加节点图普通一致性哈希算法有个潜在的问题是:节点Hash后会不均匀地分布在环上,这样大量的Key在寻找节点时,会存在命中各个节点的概率差别较大,无法实现有效的负载均衡。如有三个节点Node1,Node2,Node3,分布在环上时三个节点挨的很近,落在环上的key寻找节点时,大量key顺时针总是分配给Node2,而其它两个节点被找到的概率都会很小。这种问题的解决方案有:改善Hash算法,均匀分配各节点到环上;使用虚拟节点的思想,为每个物理服务器节点在圆上分配100~200个点。这样就能抑制分布不均匀,最大限度地减小服务器增减时的缓存重新分布。用户数据映射在虚拟节点上,就表示用户数据真正存储位置是在该虚拟节点对应的实际物理服务器上。1.4M的Java客户端实现(集群)1.4.1Google的Memcached实现官方推荐的Java客户端之一Whalin开源实现基础上做再次封装的产物。增加实现了缓存服务接口化,使用配置文件代替代码初始化客户端,集群的实现,LocalCache客户端本地缓存的使用。旧SocketIO代码里面有太多的Synchronized(同步),多多少少会影响性能,改造SocketIO部分,优化Synchronized,添置了读入缓存页。接口类图集群、客户端的初始化通过配置文件生成,配置内容如下:集群中多节点软负载均衡,当前采用简单的Hash算法加取余来分发数据,数据在多节点上进行异步冗余存储,防止数据丢失,数据在分发到某一失败节点时可以转向到其他可用节点,节点恢复可用后数据Lazy复制,例如,当A,B两台机器作为集群的时候,如果A出现了问题,系统会去B获取数据,当A正常以后,如果应用在A中没有拿到数据可以去B获取数据,并且复制到A上。1.4.2Spring+XMemcached实现M的Java客户端中,XMemcached支持所有的文本协议和二进制协议。支持动态添加和删除M节点。支持客户端统计。支持节点的权重设置,支持nio的连接池,网路实现层是长连接形式,无需重复创建多个Client对象,在高负载环境下提高吞吐量。利用Spring框架可以直接配置客户端集群,按照规定算法(Ketama等),自动Build出客户端对象,具体如下图。集群服务配置图客户端对象配置图2缓存Redis(R)2.1R的简介redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)和zset(有序集合)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。2.2R的master-slave(主从)架构图2.1master-slave模式当设置好slave服务器后,slave会建立和master的连接,然后发送sync命令。无论是第一次同步建立的连接还是连接断开后的重新连接,master都会启动一个后台进程,将数据库快照保存到文件中,同时master主进程会开始收集新的写命令并缓存起来。后台进程完成写文件后,master就发送文件给slave,slave将文件保存到磁盘上,然后加载到内存恢复数据库快照到slave上。接着master就会把缓存的命令转发给slave。而且后续master收到的写命令都会通过开始建立的连接发送给slave。从master到slave的同步数据的命令和从client发送的命令使用相同的协议格式。当master和slave的连接断开时slave可以自动重新建立连接。如果master同时收到多个slave发来的同步连接命令,只会使用启动一个进程来写数据库镜像,然后发送给所有slave。流程如下图所示:图2.3redis主从数据复制流程Redis复制机制的缺陷从上面的流程可以看出,Slave从库在连接Master主库时,Master会进行内存快照,然后把整个快照文件发给Slave,也就是没有象MySQL那样有复制位置的概念,即无增量复制,这会给整个集群搭建带来非常多的问题。比如一台线上正在运行的Master主库配置了一台从库进行简单读写分离,这时Slave由于网络或者其它原因与Master断开了连接,那么当Slave进行重新连接时,需要重新获取整个Master的内存快照,Slave所有数据跟着全部清除,然后重新建立整个内存表,一方面Slave恢复的时间会非常慢,另一方面也会给主库带来压力。所以基于上述原因,如果你的Redis集群需要主从复制,那么最好事先配置好所有的从库,避免中途再去增加从库。redis的master/slave模式下,master提供数据读写服务,而slave只提供读服务。客服端通过ConsistentHashing算法选择要访问的slave缓存服务节点,运行图如下图所示:图2.2redis运行图2.3R的特性可以将缓存数据持久化到磁盘不支持集群,但支持主从模式value支持数据类型:string(字符串)、list(列表)、sets(集合)或者是orderedsets(被排序的集合)和hash(哈希)。基于客服端来实现分布式(通过ConsistentHashing算法选择服务器节点,算法详情请参考1.4节)事务支持(MULTI,EXEC及DISCARD三个命令让Redis的使用者可以将Redis命令打包进行原子性的操作)支持Publish/subscribe(使用该功能可以很容易实现一个实时消息平台)2.4R的Java客户端实现redis主页上列出的java客户端有Jedis、JRedis和JDBC-Redis三种,面分别介绍三种客户端的优缺点。支持redis版本性能维护推荐Jedis2.0.0releasefastactivelydeveloped推荐JRedis1.2.nrelease2.0.0尚未release版本fastJDBC-Redisnotgood详情请参考:(1)、jedis实现jedis是Redis官方首选的Java客户端开发包,推荐使用jedis,所有对redis操作类的结构非常明确,都通过jedis获取其他的类,且jedis支持和spring集成。以下是jedis+spring集成步骤:首先,在项目中引入jeids的jar包:其次,在spring配置文件中添加配置:其次,在spring配置文件中添加配置:!--javareadis客户端--dependencygroupIdredis.clients/groupIdartifactIdjedis/artifactIdversion2.0.0/version/dependency最后,应用程序调用:(2)、jredis实现实现比较复杂,且版本比较旧,不支持redis的很多新特性。(3)、jdbc-redis实现jdbc-redis是用于redis这个NoSQL数据库的jdbc驱动,也就是说你可以使用你所熟悉的jdbc的方法来访问Redis数据。但是jdbc-redis性能较差,不推荐使用。2.5R的最新版本2.4改进对小数据量的sortedsets结构的内存使用做很大的优化beanid=jedisPoolConfigclass=redis.clients.jedis.JedisPoolConfigpropertyname=maxActivevalue=50/propertyname=maxIdlevalue=10/propertyname=maxWaitvalue=1000/propertyname=testOnBorrowvalue=true//beanbeanid=jedis.shardInfoclass=redis.clients.jedis.JedisShardInfoconstructor-argindex=0value=127.0.0.1/constructor-argindex=1value=6379type=int//beanbeanid=shardedJedisPoolclass=redis.clients.jedis.ShardedJedisPoolconstructor-argindex=0ref=jedisPoolConfig/constructor-argindex=1listrefbean=jedis.shardInfo//list/constructor-arg/beanShardedJedisjedis=shardedJedisPool.getResource();jedis.get(key);//从redis服务器获取值jedis.set(key,value);//将值保存到redis服务器RDB文件的持久化速度也将会大大提高对目前的一些写操作命令进行了改进,支持批量写入功能启用新的内存分配模式jemalloc通过对copyonwrite机制使用的优化,数据持久化保存的子进程的内存占用将大大减少INFO内容更加丰富新的OBJECT命令,提供对Redis存储va

1 / 20
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功