一.为何选择redisjava
在项目中使用redis作为缓存,尚未使用memcache,考虑因素主要有两点:mysql
1.redis丰富的数据结构,其hash,list,set以及功能丰富的String的支持,对于实际项目中的使用有很大的帮忙。(可参考官网redis.io)redis
2.redis单点的性能也很是高效(利用项目中的数据测试优于memcache).sql
基于以上考虑,所以选用了redis来作为缓存应用。数据库
二.分布式缓存的架构设计缓存
1.架构设计数据结构
因为redis是单点,项目中须要使用,必须本身实现分布式。基本架构图以下所示:
2.分布式实现架构
经过key作一致性哈希,实现key对应redis结点的分布。分布式
一致性哈希的实现:ide
l hash值计算:经过支持MD5与MurmurHash两种计算方式,默认是采用MurmurHash,高效的hash计算。
l 一致性的实现:经过java的TreeMap来模拟环状结构,实现均匀分布
3.client的选择
对于jedis修改的主要是分区模块的修改,使其支持了跟据BufferKey进行分区,跟据不一样的redis结点信息,能够初始化不一样的 ShardInfo,同时也修改了JedisPool的底层实现,使其链接pool池支持跟据key,value的构造方法,跟据不一样 ShardInfos,建立不一样的jedis链接客户端,达到分区的效果,供应用层调用
4.模块的说明
l 脏数据处理模块,处理失败执行的缓存操做。
l 屏蔽监控模块,对于jedis操做的异常监控,当某结点出现异常可控制redis结点的切除等操做。
整个分布式模块经过hornetq,来切除异常redis结点。对于新结点的增长,也能够经过reload方法实现增长。(此模块对于新增结点也能够很方便实现)
对于以上分布式架构的实现知足了项目的需求。另外使用中对于一些比较重要用途的缓存数据能够单独设置一些redis结点,设定特定的优先级。另外对 于缓存接口的设计,也能够跟据需求,实现基本接口与一些特殊逻辑接口。对于cas相关操做,以及一些事物操做能够经过其watch机制来实现。(参考我以 前写的redis事物介绍)
以上是基于redis分布式架构的介绍!可是应用中读写都是在一块儿的。相关写是在应用操做后flush或者update的,有必定的耦合。为了使读 写分离,以及缓存模块跟应用的耦合更小,考虑使用mysql binlog来刷新缓存。如下是基于binlog刷新可性行分析以及实现过程当中须要注意的地方。
三.采用binlog架构刷新缓存可行性分析
1.Mysql日志格式介绍可参考我之前的的介绍。
2.对于使用MIXED日志格式,此日志格式,记录的是对应数据库操做的SQL语句,采用此日志方式存在的问题:
l 对于一些未任何更新操做的SQl语句,像条件不知足,对应的sql也会记录到binlog日志中。
l SQL语句记录的未必包括全部的更新操做。
l 对于一些分布式数据库,对于SQL中的where条件指定的是非均衡字段,也许会存在多条SQL,跟设计有关!
基于以上考虑,采用MIXED的日志格式进行binlog解析是行不通的。(官网给出的指示是failed statementsare not logged ,但不包括语法没错误,更新条件不符合对应的SQL)
3.采用ROW日志格式
对于此日志格式,每行变化都有对应的记录,此日志格式,对于解析及采集数据都是很是方便的,也只有采用此日志格式,才能基于binlog修改,作刷新缓存相关方案的设计。可是基于此日志格式也存在一些问题:
l 须要考虑项目中是否有大量的批量的update操做,若是采用此日志格式,批量操做每一行修改都会记录一条日志,大量的批量操做所产生的日志量,以及所带来的IO开销是否能够接受。
经过以上分析,最终项目中仍是考虑基于ROW日志格式进行缓存刷新,还有一个问题须要考虑,在应用层DB进行了相应的update操做后,所产生的 Binlog是会带来必定的延迟,若是Binlog处理模块正常运行,数据是的延迟会很是少,MS级别之内,对用户体验是没有感知的,可是Binlog模 块是多点,异常,以及相应的延迟确定会是存在的,这样,缓存数据确定会存在脏数据。
不过经过以上方案,数据能达到最终一致性,所以how to权衡,须要考虑。
经过以上分析,是否采用Binlog来作缓存数据刷新相信你们有一个基本概念了
四.基于binlog刷新缓存的实现时注意的地方
1.若是是采用java作相关开发,可使用开源的tungstenAPI
2.Binlog日志解析是按照mysql 的master/slave同步流程来实现,即一个线程同步,一个线程解析。
3.设计是可分Binlog处理模块以及缓存处理SqlEvent两部分,其中Binlog处理解析好对应的SqlEvent,而后对应的缓存刷新处理SqlEvent,一个简单的生产者-消费者模式。
4.对于多个Binlog处理模块能够是单点,也能够是经过一些协同工具来管理,看需求。可使用ZooKeeper等。
5.对于分布式缓存中的数据,对于Binlog来刷新的缓存数据会存在load数据的问题,为了减轻DB的额外压力,flush操做可在get缓存数据处完成。看需求,若是读写彻底分享的话此DB的额外压力能够接收的话也可行。
6.对于缓存数据性一致性要求比较高的,能够经过版本号来控制,即在应用层引入必定的耦合,在DB操做时带mark ,缓存刷新是也mark,另外get操做时比较双版本号来达到数据的一致性。(此跟5谈论的必定的联系,读写是否彻底分离,以及相应一致性实现的一些方法)
五.一点心得
前先后后,对redis完成调研,以及相关的一些使用,分布式缓存的实现,基于binlog方式的修改等,接触有一年多了,这段时间下来,学了不少,以上算是一点小记,这部分工做的一点小记。实现过程当中存在更多的问题。
对于调研相关的一些工做,必定要作的仔细,相应的细节必定要了解透彻,不然也许一此小问题会致使整个方案的不可行,甚至更大的的问题。连锁反应!