缓存更新策略(一)
缓存的引入能够帮助DB减轻检索压力,但是如果不能很好的处理数据一致性的问题,那么会导致读取脏数据的问题,解下来2篇文章就总结下几种缓存更新策略:
如果更新缓存
- 先更新DB,再更新缓存
- 先更新缓存,再更新DB
如果删除缓存
- 先删除缓存,再更新DB
- 先更新DB,再删除缓存
缓存的引入能够帮助DB减轻检索压力,但是如果不能很好的处理数据一致性的问题,那么会导致读取脏数据的问题,解下来2篇文章就总结下几种缓存更新策略:
如果更新缓存
如果删除缓存
上一篇文章提到了2个观点: 缓存必须设置过期时间,可以保证数据的最终一致性。在数据发生变更的同时,重新建立缓存是没有必要的操作。 同时提到了数据更新的时候,删除缓存和更新DB,哪个操作应该先行了? 本文同上一篇文章一样,假设在不为缓存添加过期时间极端情况下,进行思考。 先删除缓存,再更新DB先更新DB,再删除缓存
这篇文章算是对之前阅读、学习、实践的一个总结。 本文主要是讲讲在Spring中,通过@Autowired之类注解,注入的对象到底是什么? 同时引申出一些关于:AOP使用的一些细节。
本文主要介绍SpringMVC对Controller
中对外方法的参数的解析接口HandlerMethodArgumentResolver
,包括如下说明:
项目需要通过代理对SpringBoot进行部分监控,业界最有名的是可能是SpringBootAdmin了,之前也有过了解,界面和作用都挺好看的,本次好奇心驱动下,探究了下源码。 分别从1.X和2.X版本来理解,本文主要是其思想,时间关系不涉及太多源码,其实其源码也很少,相信大家能够搞定。
Netty 是一个性能强健的 网络通信库。 很多开源项目都是使用其作为底层的通信框架,比如 Dubbo,Kafka等。之前用 Netty做过项目,写了一个基于命令模式的通信框架,后续有机会整理后,分享出来,哪个命令模式的框架其实很简单,我都不好写出来,不过它确实是支撑了有些利国利民的项目。后续有机会分享。 Netty概念很多,写 demo 很容易,但是要精通的或者说是入门的话,不下一番苦功夫是不行的。 今天翻看了之前的 Netty 记录的比较,将所有的概念整理后出了一副图,我们围绕图来说说 Netty的架构。
lombok这个插件非常好用,通过简单的注解就能省略很多冗余代码,常规的:@Data,@Getter/@Setter,@Slf4J这些基础的我就不写了,随便一百度就可以知道。 今天我们来讲讲几个冷门但是却好用的注解: @NonNull@Cleanup@SneakyThrows@Synchronized
本文作为一个总结,主要是对Spring Cloud的部分组件原理进行一个提纲挈领的总结。具体的实现,后续有机会分享,网上也有很多。本文主要概括下 Ribbon 和 Feign的原理。
Feign在Github上开源了一个项目,可以更加方便的利用Feign进行文件传输和多参数传输。 项目地址:https://github.com/OpenFeign/feign-form 这篇文章就结合官方的Test总结下用法。
最近工作和心态发生了一点变化,对未来的自己提出了更高的要求,所以在阅读和思考上,更加严格的要求自己的了。 之前临时看了一本书《分布式服务架构:原理、设计与实战》,因为时间缘故,很多点都没有看到,现在相对时间充足了点,所以一边读,一边做总结。 记录、分析、总结、提高! 微服务和SOA的区别 SOA强调异构服务通过一个总线进行协作,有一个中心化的企业服务总线。微服务是没有这样一个总线的。 去中心化的理解 服务的核心数据:信息,没有在某个地方聚合进行传输。ESB不是去中心化,因为信息在企业服务总线进行了聚合。 流量都走网关的问题 前段时间和用户交流SpringCloud过程中,用户认为所有服务的流量都是通过了API网关进行了转发。 为了解释这个问题在交流过程中,提出了外部应用和内部应用2个概念。内部应用就是在Eureka Server这类服务注册中心进行了注册的服务。外部应用反之。 内部应用因为在EurekaServer进行了注册,所以获取到内部服务节点的IP等关键信息,所以可以直接发起访问。 外部应用涉及到安全等原因,不能够获取到内部应用真实的IP地址,所以只给你暴露一个API网关的....
这篇文章主要是记录我对JVM中7和8的一些理解误区,之前JVM的知识主要来自于《深入理解JVM虚拟机第二版》,但是其实根据JDK7来谈的,所以和当前用的最大的JDK8还是有区别的,对部分概念没有深刻的对比,这里简单记录下。 本文主要是对 方法区和 Metaspace进行概括! 触类旁通,博闻强识! 方法区 方法区也就是永久代或者PermGen Space,这3个概念是一致的。 这篇文章前,我一直以为不是同一个东西,但是又很纳闷为什么说方法区和永久代存储的都是Class的信息,这里突然顿悟啦! 在JDK7中其主要是存放:类信息、常量池、静态信息、JIT及时编译的数据。 当类非常多的时候,可能会报错java.lang.OutOfMemoryError: PermGen* Metaspace 在JDK8后,方法区被移除了,引入了新的空间Metaspace来存放类的信息。 Metaspace不在虚拟机中,而是使用本地内存,这样困扰我们的PermenGen的内存就不存在了,其上限变成了物理内存,当然可以通过参数进行设置。 -XX:MetaspaceSize=8m -XX:MaxMeta....
之前有被问到一个问题,远程RPC调用的情况下,如何更方便、更高性能的依赖外部服务提供者提供的接口进行测试。 这其实也是一个很容易遇到的问题,微服务架构下,团队开发各自的模块,当自己模块开发完成后,如果需要进行测试,有可能外部依赖方还没有完成,也有可能需要第三方服务带来的影响,这个时候就需要通过Mockd的方式进行处理。 这里我记录下我最新学习到的知识,应该不全面,有更好,更优质的解决方案,还请留言指出。 通过Mock软件:Mock Server、Moco 这类软件模拟服务提供者。通过Filter拦截本地对第三方的请求,替换为调用本地写好的方法。 吾日三省吾身:为人谋而不忠乎?与朋友交而不信乎?传不习乎? Mock方式 通过第三方工具Mock模拟的方式,需要考虑如下几个问题: 接口报文的序列化方式,如果是JSON还挺方便,但是如果是其他序列化,比如protobuf、thrift这些,模拟起来就不方便了。如果消费端是集群,需要开启多个Mock模拟器,同时如果是TCP通信的还不好做无侵入的负载均衡,HTTP通信还可以利用Nginx做服务端负载均衡。 综上:采用Mock这种方式,适用....
SpringBoot提供了非常方便的将 tomcat一起打包后为jar一键启动的方式。 因为项目原因,需要将项目打包为war 包部署,所以经过查阅官方文档,将处理方式简单记录下,方便后续排查。 识迷途其未远,觉今是而昨非! 步骤 启动类继承 SpringBootServletInitializer重写启动的configure @SpringBootApplication public class Application extends SpringBootServletInitializer { /** * 重写configure 方法。 * 通过形参 application 的 source 方法启动启动类 Application */ @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(Application.class); } public static void main(Stri....
Java程序启动的时候,不会一次性的将程序需要用到的所有类加载到内存中。JVM会先加载基础类,其他类等到需要使用的时候再进行加载。 什么叫做“需要使用的时候”了?通常而言有如下几种情况: 通过new关键字第一次使用非基础类,比如自己定义的PersonService这类的。通过Class.forName()的时候。访问某一个非基础类的静态成员的时候。 JDK默认的类加载器 简单而言:JDK默认提供了3个ClassLoader,Bootstrap、Extension、App 3个,前2者通常用于加载JDK自身的jar或者class,app加载的是我们开发过程中引入的包。 Bootstrap Classloader Bootstrap Classloader时C++编写的最底层的类加载器,它会加载系统最底层的类,比如rt.jar和charsets.jar这些类。 可以通过如下代码获取加载了哪些 URL[] urls = sun.misc.Launcher.getBootstrapClassPath().getURLs(); for (int i = 0; i < urls.leng....
有句话说得好:基础不好,代码写不好。(0.0 这话我编的...) 之前对于提到的几个 API 没有很好的理解,趁着今天在使用,所以梳理一下。 静态方法:Class.forName(“xxx”) 的作用非静态方法 clazz.newInstance() 的作用直接通过 new的区别 Class.forName("xxx") 作用 老规矩,先上代码: Class<?> clazz = Class.forName("club.hicode.daydayup.reflect.RefPerson"); 从上述代码可以看出3点: forName 是一个Class的静态方法,通过Class 直接调用。forName 中需要给出一个 全路径的包+类 forName返回值是一个 Class对象。 这个 API 有什么作用了? 如果要了解静态方法Class.forName(“xxx”) 的作用,需要了解JVM 中类的加载机制,这里不展开讲。 简单而言就是要使用某一个类,那么必须先从 .class 的二进制文件加载到JVM中。forname 就是起到的就是这个作用。 这个时候你可能会想,....