Guava的EventBus使用
Guava中提供了一种事件总线(EventBus)的技术,是观察者模式的一种实现。jdk中也提供了Observer的接口,Guava的优势是更易于使用,并且提供了同步和异步的通知机制。
简介Guava中提供了一种事件总线(EventBus)的技术,是观察者模式的一种实现。jdk中也提供了Observer的接口,Guava的优势是更易于使用,并且提供了同步和异步的通知机制。观察者模式,在软件的开发中有广泛的应用,用于模块之间的解耦。比如,订单系统中,当创建订单后,会向客户、商家发送通知,由他们进行不同的处理。
优点:
编程简单,异步,同步,异常处理方便;
单机模式,不需要额外的组件依赖。
缺点:单机,消息没有持久化。
对消息敏感,或者高吞吐情况下,还是要使用MQ。
使用引入如下的依赖:
12345<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>30.0-jre</ver ...
MySQL性能分析工具explain的使用
MySQL 提供了一个EXPLAIN命令,它可以对SELECT语句进行分析,并输出SELECT执行的详细信息, 以供开发人员针对性优化。本文介绍它的使用,及如何分析输出。
使用使用很简单,在sql语句前面加上explain关键词即可,或者使用类似navicat等可视化工具,自带的解释。
1explain SELECT * FROM user_info where user_account like 'lisi%'
输出字段的介绍explain的输出如下:各列的含义:
id:select查询的标识符,自动分配的;
select_type:select查询的类型;
table:表名
partitions:匹配的分区;
type:join类型
possible_keys:此次查询中可能选用的索引
key:此次查询确切用到的索引
ref:哪个字段或常数与key一起被使用
rows:显示此查询一共扫描多少行,是个估计值
filtered:表示此查询条件所过滤的数据的百分比
extra:额外的信息
设计模式六大原则
设计模式(面向对象设计)六大原则,具体如下:
单一职责原则(类和方法,接口)
开闭原则(扩展开放,修改关闭)
里氏替换原则(基类和子类之间的关系)
依赖倒置原则(依赖抽象接口,而不是具体对象)
接口隔离原则(接口按照功能细分)
迪米特法则(类与类之间的亲疏关系)
参考文档
单一性原则定义一个对象不应该承担过多的职责(类变化的原因)。规定一个类应该有且仅有一个引起它变化的原因,否则就应该被拆分。
优点单一性原则控制类的粒度大小,将对象解耦,提高内聚性。优点如下:
降低类复杂度,一个类只负责一项职责;
提高类的可读性;
提高类的可维护性;
降低变更引起的风险。
开闭原则定义开闭原则(Open Closed Principle,OCP)由勃兰特·梅耶(Bertrand Meyer)提出,他在 1988 年的著作《面向对象软件构造》(Object Oriented Software Construction)中提出:软件实体应当对扩展开放,对修改关闭(Software entities should be open for extension,but closed for modi ...
索引失效的情况
索引失效的几种情况:
违反最左前缀法则,缺少左边索引字段
在索引列上进行操作,函数操作
索引范围条件的右边索引会失效
尽量使用覆盖索引,select索引字段
使用!=或<>会使索引失效
like以通配符开始
字符串不加单引号索引失效
or连接
order by 和group by时不能违反最左前缀,即order by或者group by的字段要是索引,并且与前面的where条件不能违反最左前缀。
ACID特性的实现原理
ACID是衡量事务的四个特性:
原子性(Atomicity)
一致性(Consistency)
隔离性(Isolation)
持久性(Durability)
MySQL的事务是如何实现这个特性的呢?
持久性持久性相对简单一点。Innodb为例。
定义持久性是指事务一旦提交,它对数据库的改变是永久性的,如果出现故障也不会改变。
实现原理Innodb引擎为了读写数据的效率,引入了一个叫做Buffer Pool的缓冲区,是对磁盘中一部分数据的映射,查询修改的时候会先对这个缓冲区就行操作,过一段时间后,会将修改刷入到磁盘。这样做的弊端是缓冲区还没刷新修改的时候,服务宕机,导致修改不能落盘,也就丢失了数据。故使用redo log,当数据修改的时候,除了修改Buffer Pool,也在redo log中记录这个操作,当事务提交后,首先会对redolog刷盘,重启服务后,会读redolog,重做这个操作,保证数据不会丢失。wal(write-ahead logging)先写日志,再更新buffer pool,刷脏成功后,redlog也就没用了。
redolog写入磁盘快:redolog每次都 ...
如何保证redis缓存与数据库数据一致性
一般在系统中为了用户的体验,需要加上缓存来提升用户的体验。一般对实时性比较高的数据,可以不添加缓存;对于读多写少的数据,或者比较耗时的需要加缓存,并且要设置过期时间,或者更新数据的时候失效;另外一种基本不变的字典数据,则可以把过期时间设置长一点,或者直接使用jvm缓存,map等去存储。那么,不可避免的问题是,你更新了数据库,缓存怎么去更新呢,才能保证与数据库中数据的一致性。一般大致有四种方法(一般缓存的数据都是经过接口调用后组合的数据,更新缓存的代价太大,因此不需要更新缓存,直接删除即可):
先更新数据库,后更新缓存
先更新数据库,后删除缓存
先更新缓存,后更新数据库
先删除缓存,后更新数据库
先删除缓存,再更新数据库** 采用延时的策略,确保更新数据的事务已经提交之后,再删除redis缓存**
这种方法一般是针对单机数据库有用,如果采用主从架构的数据库,会有一定的延迟,查询查的是从库,数据还没同步过来呢,容易查出旧的数据。
主从结构的话可以通过:如果是redis缓存中没有数据,需要查询数据库的时候,强制查询主数据库,填充redis缓存这样就没问题了。
先更新数据库,再删除缓存 ...
消息队列如何保证消息的可靠传输
由于网络延迟、机器等原因,消息队列可能出现消息的丢失,那么如何解决这个问题呢。
RabbitMQ生产者丢了数据生产者发送消息的时候,可能网络原因没有到达消息队列保存。RabbitMQ提供了事务的处理,发送消息前开启一个事务channel.txSelect,然后发送消息,如果消息没有被mq收到,那么生产者会抛出异常,并回滚事务channel.txRollback,重新发送数据,如果成功收到,则提交事务channel.txCommit。还有一种方法是,确认机制,每次写消息都会生成一个唯一的id,写成功后会收到一个ack,如果没有处理,要调用nack回调,重新发送。这一过程是异步的。
mq本身丢失了数据开启 RabbitMQ 的持久化,消息写入之后会持久化到磁盘, RabbitMQ 挂了,恢复之后会自动读取之前存储的数据,一般数据不会丢。RabbitMQ 还没持久化,就挂了,可能导致少量数据丢失,这个概率较小。
消费端丢失数据RabbitMQ 如果丢失了数据,主要是因为消费的时候,刚消费到,还没处理,结果进程挂了,RabbitMQ 认为消费了,数据就丢了。这个时候得用 RabbitMQ ...
MySQL中的几种日志
MySQL中主要有六种日志文件,分别是:重做日志(redo log)、回滚日志(undo log)、二进制日志(binlog)、错误日志(errorlog)、慢查询日志(slow query log)、一般查询日志(general log),中继日志(relay log)。他们在MySQL中扮演着不同的角色,在ACID中起着至关重要的作用。Innodb存储引擎为例。
重做日志(redo log)作用确保事务的持久性。一次事务可能涉及到多个磁盘页的写,redo log就是为了防止数据库忽然宕机,尚有没有来得及写的磁盘页。重启服务后会依据redo log重做,从而保证事务的持久性。
生命周期事务开始后,产生redo log,首先会写入到内存,然后异步刷盘到redo log文件中;当对应的事务的脏页数据写入磁盘之后,redo log就没存在的必要了。
存储结构分为逻辑结构和物理结构:逻辑结构,使用LSN(Log sequence number)记录编号,表示当前写入的总的日志的字节数。物理结构,定长的文件,每512字节一个Block,循环使用。
LogBlock中的日志存储方式:
类似 ...
Maven中scope的含义
Maven依赖中有个scope元素,控制依赖jar包的使用范围。用的不当,容易造成jar包冲突,程序异常等。通常有:compile、runtime、provided、test、system、import。
compile(编译):不指定时,默认。表示该依赖的jar包,参与编译、测试、打包、运行等阶段。runtime(运行时):编译的时候不需要这个jar包,但是会参与项目的测试和运行,比如jdbc具体的实现类,常用的lombok都可以设置为runtime。provided(已提供):被依赖项目理论上可以参与编译、测试、运行等阶段,相当于compile,但是再打包阶段做了exclude的动作。适用场景:例如, 如果我们在开发一个web 应用,在编译时我们需要依赖 servlet-api.jar,但是在运行时我们不需要该 jar 包,因为这个 jar 包已由应用服务器提供,此时我们需要使用 provided 进行范围修饰。test(测试):表示被依赖项目仅仅参与测试相关的工作,包括测试代码的编译,执行。常见的Junit测试。system(系统):ystem 元素与 provided 元素 ...