CacheDB
词汇表
英文 | 中文 | 备注 |
---|---|---|
CacheService | 缓存服务器 | 与缓存数据库进行交互的服务器 |
CacheDB | 缓存服务器 | 存储数据的缓存数据库 |
一、概述
承担的需求(主要秘密)
缓存数据库模块主要负责存储缓存服务器需要进行缓存的商品数据,并提供缓存服务器需要进行访问的缓存商品数据。
可能会修改的实现(次要秘密)
- 缓存数据库
- 缓存更新算法
- 缓存访问算法
涉及的相关质量属性
- R1 数据可靠性
- R4 更新数据时系统可用
- R9 保证存取效率
- R10 高峰吞吐量
设计概述
需要考虑的核心问题为:如何保证高并发、高可用?
本模块负责提供存储和提供缓存的商品数据的数据库,根据业务需求,着重关注在高并发情况下的稳定性,以及对自身的可用性
- 保证稳定性的主要手段是:当请求进入时,首先交给分流器处理,如果当前的负载比较高,分流器就会讲请求分发到注册的从属服务器来处理
- 在高并发的情况下,从属服务器的查询分发策略对整体性能的影响尤为重要,故分流器在查询从属服务器的过程中需要应用不同的查询方式,同时为了保证查询方式的可扩展性,故以策略模式来构建查询方式的维护类
角色
CacheServer: 向CacheDB发送存储和访问缓存商品数据的请求 CacheDB: 处理所有由缓存服务器发送的请求,进行缓存商品数据的存储和访问
模块对外接口
- Iterator<Comment> getCommentsByCommodityId(int cid);
- void addComment (int uid , int cid , String content);
- void deleteComment (int cid):void;
二、类的设计
2.1 类描述
CommentServiceImpl类
类职责
该类负责处理实际的业务调用,是与其他模块进行交互的接口,当调用其来请求数据操作时,实际上会发送请求到由本模块其他部分构成的数据访问中间件。
类方法
- public Iterator getCommentsByCommodityId(int id);
- 职责:根据商品ID获取该商品的全部评论(核心接口)
- 前置条件:无
- 后置条件:返回商品的评论数据
- public void addComment(int uid , int cid , String content);
- 职责:持久化评论
- 前置条件:成功购买商品
- 后置条件:持久化评论信息
- public void deleteComment(int cid)
- 职责:删除评论
- 前置条件:用户为评论发布者或者管理员
- 后置条件:删除评论信息
RequestDispatcher类
类职责
该类负责转发数据请求,首先请求转发器会根据请求中的参数商品号和分区策略决定存储该商品的评论数据的分区号,然后根据请求的类别决定是否进行负载均衡。写操作不需要进行负载均衡,直接转发到分区号对应的节点的主服务器进行写请求处理;读操作在转发之前需要根据负载均衡策略从目标节点中挑选合适的服务器然后再转发读请求。
类方法
- public int getServerId(int num)
- 职责:根据分区号计算响应写请求的服务器ID
- 前置条件:有新的写请求到达,并且已经确定分区号
后置条件:返回服务器ID
public void dispatch(int num):
- 职责:根据服务器ID把请求转发到相应的服务器
- 前置条件:无
- 后置条件:转发请求
RequestParser类
类职责
本类的职责主要是分析请求的内容,获取商品Id,确定请求的类型。将该类从RequestDispatcher中分离出来是出于单一职责的考虑。
类方法
- public int getCommodityId(Request r);
- 职责:提取请求参数中的商品ID用于转发器处理
- 前置条件:有新的请求到达
- 后置条件:返回商品ID
- public boolean isReadRequest(Request r);
- 职责:判别请求的读写类别用于转发器区分处理
- 前置条件:有新的请求到达
- 后置条件:返回判断结果
PartitionStrategy接口
类职责
由于分区的方式有很多,为了应对未来可能的对算法变更,我们应将行为抽象成接口,并将实现放在策略类的具体实现类中。HashStrategy和ModStrategy是目前采用的两种策略,HashStrategy是采用hash函数,将商品ID作为输入散列到节点数组中去;ModStrategy则是把商品ID对节点数组长取模然后确定数组下标。
类方法
- public int getPartitionNum(Request r);
- 职责:根据商品ID和分区策略计算分区号
- 前置条件:有新的请求到达
- 后置条件:返回分区号
BalanceStrategy接口
类职责
由于负载均衡的方式有很多,为了应对未来可能的对算法变更,我们应将行为抽象成接口,并将实现放在策略类的具体实现类中。AverageStrategy和MinStrategy是目前采用的两种策略,AverageStrategy是采用循环分配的方式,例如该节点有ABC三台服务器,则每当有新的请求时就循环地发送给A、B、C三个服务器; MinStrategy是根据每个服务器当前的请求负载量来确定转发目标的,每次将新请求转发给负载最小的服务器。
类方法
- public int getServerIdWithLoadBalance (int num)
- 职责:根据分区号和负载均衡策略计算响应读请求的服务器ID
- 前置条件:有新的读请求到达,并且已经确定分区号
- 后置条件:返回服务器ID
Server类
类职责
Server类其实是对可用的服务器资源的抽象表示,包含唯一的标识符ID和当前的状态Status,并提供处理请求的方法。
类方法
- public Response handleRequest(Request r);
- 职责:处理请求返回响应
- 前置条件:有请求到达
- 后置条件:发送响应
- public Status getStatus();
- 职责:返回服务器当前状态
- 前置条件:无
- 后置条件:返回状态
- public int getId();
- 职责:返回服务器ID
- 前置条件:无
- 后置条件:返回ID
- public void setId(int i);
- 职责:设置ID
- 前置条件:无
- 后置条件:设置ID
Node类
类职责
Node类其实是对服务节点的抽象表示,每个节点包含一个主服务器和若干从服务器
类方法
- public Server getMaster();
- 职责:获取当前节点的主服务器
- 前置条件:无
- 后置条件:返回主服务器引用
- public void setMaster(Server s);
- 职责:设置当前节点的主服务器
- 前置条件:无
- 后置条件:变更当前节点的主服务器
- public Iterator getSlaves();
- 职责:返回获取当前节点的从服务器
- 前置条件:无
- 后置条件:返回当前节点的从服务器
- public void setSlaves(Collection
s); - 职责:设置当前节点的从服务器
- 前置条件:无
- 后置条件:变更当前节点的从服务器
NodePool类
类职责
本类是节点池的维护类,转发器包含其引用,将请求发送到适合的服务器上。该类包含一个节点的数组,并提供增添的方法,另外当服务器出现故障时,会被监视器通知更新节点池。该类实际上是监视器类的一个观察者。
类方法
- public void register(Node node);
- 职责:注册一个节点
- 前置条件:有新的可用节点出现并且当前节点池中不存在
- 后置条件:往节点池中添加一个节点
- public void remove(Node node);
- 职责:删除一个节点
- 前置条件:该节点不再存在
- 后置条件:从节点池中删除一个节点
- public void updateNode(int i, Node n);
- 职责:更新一个节点
- 前置条件:该节点当前故障或者出现其他变更需求
- 后置条件:更新一个节点
- public Node[] getNodes();
- 职责:返回节点数组
- 前置条件:无
- 后置条件:返回节点数组
Monitor类
类职责
该类负责在项目启动时从配置文件中获取全部服务器的连接信息,然后根据此信息去尝试连接各个服务器,并按照配置将服务器组装成一个节点放入节点数组中供节电池获取。 在项目启动后,该类负责监控各个服务器,当某个服务器出现故障时会报告错误,并通知节电池更新节点。如果一个节点的从服务器故障,会创建一个不再包含故障服务器的节点,然后调用NodePool的updateNode()方法;如果一个节点的从服务器故障恢复又变为可用,会创建一个包含故障恢复的服务器的节点,然后调用NodePool的updateNode()方法如果一个节点的主服务器故障,会调用NodePool的remove()方法; 如果出现一个新的可用节点,会调用NodePool的register()方法;
节点池收到通知后会重新请求可用的节点数组,从而实现故障的检测的处理。
类方法
- public Collection
detectServer(); - 职责:检测可用的服务器
- 前置条件:无
后置条件:返回可用的服务器集合
public Node createNode();
- 职责:根据配置创建节点
- 前置条件:该节点的主服务器可用
后置条件:返回节点
public Node[] getAvaliableNodes;
- 职责:返回当前可用的全部节点
- 前置条件:无
后置条件:返回节点数组
public void reportError();
- 职责:报告错误
- 前置条件:出现服务器故障
后置条件:报告错误并记录日志
public void notify();
- 职责:通知节点池更新节点
- 前置条件:出现服务器变更
- 后置条件:发送通知
三、重要协作
四、设计模式应用
策略模式
使用策略模式将类中易于变化的行为独立出来,声明为一个行为接口然后将实现存放于具体的实现类中,以适应开闭原则,使得行为变化时仅需要添加一个新的实现类即可。 本模块中两次使用了策略模式,在RequestDispatcher中持有PartitionStrategy和BalanceLoadStrategy的引用。
迭代器模式
使用迭代器模式使得在访问一个聚合对象的内容时无需暴露它的内部表示。 本模块中两次使用了迭代器模式,在CommentService中的getCommentsByCommodityId()方法中和NodeInterface中的getSlaves()方法均返回一个迭代器。