好记性不如烂笔头。
日志级别动态调整
日志是每个项目必备的组件,这几年从开始工作接触的log4j到后来的logback,再到现在用的log4j2,日志文件
的查看从最开始的登录单台机器查看,到shell脚本一次性查看多台机器,再到后来ELK搜索搭建的可视化日志查询
系统。
日志使用不当对于高qps的服务来说会导致的线上严重的故障,所以统一化日志组件和实现日志动态降级有
很大作用。
关键源码:LoggerFactory bind()
private final static void bind() {
Set<URL> staticLoggerBinderPathSet = null;
// 1、查询所有的 org/slf4j/impl/StaticLoggerBinder.class
staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
// 2每一个slf4j桥接包中都有一个StaticLoggerBinder类,该类实现了LoggerFactoryBinder接口。
具体绑定到哪一个日志框架则取决于类加载顺序。
StaticLoggerBinder.getSingleton();
INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
reportActualBinding(staticLoggerBinderPathSet);
fixSubstituteLoggers();
replayEvents();
// release all resources in SUBST_FACTORY
SUBST_FACTORY.clear();
}
修改log日志级别
1、暴露端口(需要考虑加解密算法)
2、初始化时候缓存所有logger实例,收到监控变更的时候,更新logger的级别。
LoggerConfig loggerConfig = logger;
Level targetLevel = Level.toLevel(loggerbean.getLevel());
loggerConfig.setLevel(targetLevel);
core.LoggerContext ctx = (core.LoggerContext) LogManager.getContext(false);
ctx.updateLoggers();
mysql 性能容量评估
数据库业务特点关键词
OLTP/OLAP
OLTP看中服务器CPU,内存,写事务较多或内存不够则依赖磁盘IO
OLAP看中磁盘扫描的IO能力,部分依赖内存排序
并发请求
读写比例
数据量
冷热数据比
数据分级存储
达达-高性能服务端优化之路
达达京东到家技术公众号
1、最初技术选型
多应用,单库
2、读写分离,主库和从库
3、垂直分库,按照应用分成多个库
垂直分库过程中的经验教训,使我们制定了SQL最佳实践,其中一条便是程序中禁用或少用join,
而应该在程序中组装数据,让SQL更简单。一方面为以后进一步垂直拆分业务做准备,
另一方面也避免了Mysql中join的性能较低的问题。
4、水平分库分表
单表超千万就可以考虑分表了
大众点评账号业务高可用进阶之路
衡量一个系统的可用性有两个指标:(也就是俗称2个9,3个9的来历)
1. MTBF (Mean Time Between Failure) 即平均多长时间不出故障;
2. MTTR (Mean Time To Recovery) 即出故障后的平均恢复时间。通过这两个指标可以计算出可用性,也就是我们大家比较熟悉的“几个9”。
异地多活
数据库 账号读多写少的特性(读写比是350:1),采用了一主多从的数据库部署方案,优先解决读多活的问题
Redis不能使用一主多从,因为Redis主从同步机制会优先尝试增量同步,当增量同步不成功时,再去尝试全量同步,
一旦专线发生抖动就会把主库拖垮,并进一步阻塞专线,形成“雪崩效应”。
因此两地的Redis只能是双主模式,但是这种架构有一个问题,就是我们得自己去解决数据同步的问题,除了保证数据不丢,还要保证数据一致。
数据同步
1、相同key数据在kafka同一个partition里面,这样可以保证消费的时候有序
2、如果两个相同的key,在两地并发写,会出现数据不一致的情况,所以需要设计一个版本号概念
3、服务的缓存加载和更新
一般我们对数据库缓存的操作都是,先查缓存,如果缓存不存在再查库,然后再写缓存,
如果db数据有变化,先更新db,再删除缓存。
但是上图有一个极端的情况,如果两个线程同时操作,可能会导致脏数据
所以换成下图方式, 先查缓存,如果缓存不存在再查库,然后再写缓存(ADD),
数据更新的时候监听数据库的binlog,然后解析binlog日志,再做set操作,这样就可以保证数据只会在一个地方赋值,
同时也可以解耦缓存更新的逻辑
同时还需要一个定时任务去scan两地的数据做对比统计
领域驱动设计(DDD)
大家一直在谈的领域驱动设计(DDD),我们在互联网业务系统是这么实践的
1、敏捷实践中的重构、测试驱动设计及持续集成可以对付各种混乱问题,但是重构出来的类没有业务上的含义
只能给予一个技术维度描绘的含义,这就会导致其他人开发需求的时候不会将业务问题对应到重构后的设计模型,
导致代码继续重构
2、解决复杂和大规模软件的武器可以被粗略地归为三类:抽象、分治和知识
领域就是问题域,有边界,领域中有很多问题;
任何一个系统要解决的那个大问题都对应一个领域;
通过建立领域模型来解决领域中的核心问题,模型驱动的思想;
领域建模的目标针对我们在领域中所关心的问题,即只针对核心关注点,而不是整个领域中的所有问题;
领域模型在设计时应考虑一定的抽象性、通用性,以及复用价值;
通过领域模型驱动代码的实现,确保代码让领域模型落地,代码最终能解决问题;
领域模型是系统的核心,是领域内的业务的直接沉淀,具有非常大的业务价值;
技术架构设计或数据存储等是在领域模型的外围,帮助领域模型进行落地;
3、设计领域模型的一般步骤如下:
- 根据需求划分出初步的领域和限界上下文,以及上下文之间的关系;
- 进一步分析每个上下文内部,识别出哪些是实体,哪些是值对象;
- 对实体、值对象进行关联和聚合,划分出聚合的范畴和聚合根;
- 为聚合根设计仓储,并思考实体或值对象的创建方式;
- 在工程中实践领域模型,并在实践中检验模型的合理性,倒推模型中不足的地方并重构。
当一个对象由其标识(而不是属性)区分时,这种对象称为实体(Entity)。
当一个对象用于对事务进行描述而没有唯一标识时,它被称作值对象(Value Object)
Aggregate(聚合)是一组相关对象的集合,作为一个整体被外界访问,聚合根(Aggregate Root)是这个聚合的根节点。
一些重要的领域行为或操作,可以归类为领域服务。它既不是实体,也不是值对象的范畴。
防腐层亦称适配层
领域行为封装到领域对象中,将资源管理行为封装到资源库中,将外部上下文的交互行为封装到防腐层中,
领域服务就是通过串联领域对象、资源库和防腐层等一系列领域内的对象的行为,对其他上下文提供交互的接口。
微服务如何拆分
微服务划分的姿势
如何高效的提问
![](http://p0.meituan.net/education/81e90fe7a3a31ee68a892e79830fb61b209197.png
)