博客
关于我
业务逻辑层缓存应该设计
阅读量:453 次
发布时间:2019-03-06

本文共 3176 字,大约阅读时间需要 10 分钟。

在业务制定时很少会切入缓存设计,这通常是一种过渡设计。毕竟,在指标不明确的情况下,这属于一种过渡设计。然而,缓存切入有很多手段,在很多时候直接在WEB进行页面缓存就能带来非常高的收益效果。缓存是一种横向的数据处理应用,通常在设计中引入AOP、ICO等应用组件都可以后期切入添加。但在没有比较丰富的经验的情况下引入AOP、ICO会直接增加应用的复杂度和风险。因此,在设计时引入一种简单的缓存方式,而不带来复杂的工作成本,是一种更优的选择。

一个简单示例

以下是一个不考虑缓存应用的常见开发方式:

public class BlogService : Interfaces.IBlogService{    public IList
List(string category, int size, int index, out int pages) { Expression exp = new Expression(); if (!string.IsNullOrEmpty(category)) exp &= Blog.iD == BlogLinkCategory.blog[BlogLinkCategory.category == category]; int count = exp.Count(); pages = count / size; if (count % size > 0) pages++; return exp.List(new Region(index, size), Blog.createTime.Desc); } public IList
ListCategories() { return new Expression().List(); } public Blog Get(string id) { return (Blog.iD == id).ListFirst(); }}

简单加入缓存

List方法为例,加入缓存处理方式:

public IList
List(string category, int size, int index, out int pages){ var result = redis.Get("key"); if (result == null) { Expression exp = new Expression(); if (!string.IsNullOrEmpty(category)) exp &= Blog.iD == BlogLinkCategory.blog[BlogLinkCategory.category == category]; int count = exp.Count(); pages = count / size; if (count % size > 0) pages++; result = exp.List(new Region(index, size), Blog.createTime.Desc); redis.Set("key", result); } return result;}

这种方式在开发中比较常见,但在前期阶段没有性能要求时会增加较大的工作量。此外,缓存产品的偶合性可能达不到理想的效果,因为开发人员还需要学习具体缓存产品的API。

缓存实现的解偶

可以在设计时制定一个简单的缓存存取接口:

public interface ICached{    T Get(Func
); void Set(string key, object data);}

在设计时引入到接口定义中:

public interface IBlogService{    IList
List(string category, int size, int index, out int pages); Blog Get(string id); Blog Save(string id, string title, string keywords, string data, params string[] categories); IList
ListCategories(); ICached Cached { get; set; }}

通过这种方式,可以在逻辑层或其他层面引入缓存设计,而不会对整个代码带来较大的复杂度变化。刚开始可以引用一个完全不做任何实现的ICached,待有需要时再更换具体实现。

缓存应用简化

可以在接口中定义一些简单的委托参数,使得缓存在应用时的复用度更高:

public interface ICached{    T Get(Func
); void Set(string key, object data);}

在编写逻辑时就可以简化为:

public IList
List(string category, int size, int index, out int pages){ var cached = Cached.Get(() => { var result = new ExpandoObject(); Expression exp = new Expression(); if (!string.IsNullOrEmpty(category)) exp &= Blog.iD == BlogLinkCategory.blog[BlogLinkCategory.category == category]; int count = exp.Count(); result.Pages = count / size; if (count % size > 0) result.Pages++; result.Blogs = exp.List(new Region(index, size), Blog.createTime.Desc); return result; }, "ListKey"); pages = cached.Pages; return cached.Blogs;}

这种方式的原理很简单:Get方法内部会检查是否有对应的key,如果存在则直接返回缓存数据,否则执行Func方法获取数据并设置到缓存中。这种方式适用于处理一些条件和分页返回等场景,代码量相对较少。

总结

通过这种设计方式,在逻辑层或其他层面引入缓存设计不会对整个代码带来较大的复杂度变化。刚开始可以引用一个完全不做任何实现的ICached,待有需要时再更换具体实现。这种设计方式的优点在于降低了开发人员对缓存产品依赖的程度,但在实际业务场景中可能需要更多的参数和配置。总之,通过这种方式可以在不影响现有功能的前提下,灵活地引入缓存设计。

转载地址:http://gzxfz.baihongyu.com/

你可能感兴趣的文章
Project Euler Problem 12: Highly divisible triangular number
查看>>
ProjectEuler 2
查看>>
projection介绍及EPSG:4326和EPSG:3857的投射转换
查看>>
project打开文件时,显示无法识别此文件格式?
查看>>
Prometheus + Grafana on Kubernetes部署
查看>>
prometheus + grafana进行服务器资源监控
查看>>
Prometheus Alertmanager 告警配置详解
查看>>
Prometheus Grafana 展示平台
查看>>
Prometheus pushgateway使用详解
查看>>
Prometheus 云原生 - Prometheus 数据模型、Metrics 指标类型、Exporter 相关
查看>>
Prometheus 云原生 - 基于 file_sd、http_sd 实现 Service Discovery
查看>>
Prometheus 云原生 - 微服务监控报警系统 (Promethus、Grafana、Node_Exporter)部署、简单使用
查看>>
Prometheus 云原生 - 监控 Linux、MySQL、Redis、RabbitMQ、Docker、SpringBoot 3.x
查看>>
Prometheus 介绍
查看>>
Prometheus 安全配置详解
查看>>
prometheus 安装node_exporter, node_exporter 安装最新版 普罗米修思安装监控服务器client
查看>>
Prometheus 安装部署实战
查看>>
prometheus 持久化存储方案
查看>>
Prometheus 监控系统企业级实战
查看>>
Prometheus 监控系统简介
查看>>