人群组件与Drools规则引擎实践
这篇主要解决什么问题我后来回头看这类活动系统,最容易失控的不是规则多,而是两层逻辑混在一起:
1、人群准入写在业务代码里
2、规则命中继续写在 if/else 里
3、阶段切换时又把条件复制一遍
4、最后没人说得清“这次为什么过了,为什么没过”
所以这类能力要先拆成两层:
1、人群组件负责准入、过滤、短路
2、Drools 负责组合条件匹配和决策输出
这不是概念拆分,而是为了让执行链路能解释、能扩展、能排查。
我理解的人群组件,应该只做过滤,不做决策人群组件适合处理下面这类问题:
1、是否命中某个标签
2、是否在灰度、白名单、黑名单内
3、渠道、身份、地域是否允许进入
4、当前阶段是否允许继续往下执行
这层的特点是“过”或者“不过”,本质上是过滤器。
如果把下面这些也塞进人群组件,边界就会很快变糊:
1、新客且近 7 天未领券,命中 A 奖励
2、老客消费金额超过阈值,命中 B 奖励
3、命中标签后再结合库存、预算、时间窗决定动作
这些已经不是准入判断,而是规则决策。
人群组件的运行模型,核心是原子人群和逻辑人群真正落地时,我更倾向把人群组件拆成两层:
1、原子 ...
一次线上慢SQL与接口超时问题排查
问题现象这是一次典型的后台列表接口超时。
接口除了查主表,还会补下游状态和展示字段。高峰期一上来就开始抖:
1、列表接口平时大约 200ms ~ 300ms
2、高峰期偶发升到 3s ~ 5s
3、数据库连接占用上升,但应用 CPU 并不高
4、网关有超时报警,应用日志里经常看到分页查询耗时偏长
这类问题不能只盯一层。表面是接口超时,实际往往是分页 SQL、事务边界和补充查询叠在一起。
第一轮排查先看应用日志先补分段耗时,结果很快就出来了:主要时间都耗在列表查询。
123long start = System.currentTimeMillis();List<ActivityEntry> entryList = activityEntryMapper.selectByExample(req.toExample());log.info("queryPage cost={}ms", System.currentTimeMillis() - start);
到这一步已经能先排掉 JSON 序列化和返回组装,问题在数据库查询。
...
CompletableFuture常用实践
适用场景CompletableFuture 在业务代码里最常见的用法,主要是下面这几类:
1、一批相互独立的任务并发执行,最后统一收口
2、先按任务类型分类,再分别并发处理
3、批量过滤、批量校验、批量补充信息
4、异步线程里补 TraceId、兜底超时和异常
只收常用实践,不展开 API 说明。
常见实践一:一批任务并发执行,最后统一收口核心写法就是:先把每个请求包装成 Future,再统一 allOf 等待。
1234567891011List<CompletableFuture<TaskResult<R>>> futures = new ArrayList<>();for (Q request : requestList) { CompletableFuture<TaskResult<R>> future = new CompletableFuture<>(); CompletableFuture.supplyAsync(() -> query(reque ...
MySQL技术内幕
MySQL体系结构和存储引擎InnoDB体系架构InnoDB存储引擎的架构。图2-1简单显示了InnoDB的存储已引擎的体系架构,从图可见,InnoDB存储引擎有多个内存块,可以认为这些内存块组成成了一个大的内存池,负责如下工作:
维护所有进程/线程需要访问的多个内部数据结构。
缓存磁盘上的数据,方便快速地读取,同时在对磁盘文件的数据修改之前在这里缓存。
重做日志(redolog)缓冲。
后台线程的主要作用是负责刷新内存池中的数据,保证缓冲池中的内存缓存的是最近的数据。此外将已修改的数据文件刷新到磁盘文件,同时保证正在数据库发生异常的情况下InnoDB能恢复到正常运行状态。
后台线程1、Master Thread
MasterThread是一个非常核心的后台线程,主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性,包括脏页的刷新、合并插人缓冲(INSERT BUFFER)、UNDO页的回收等。
2、IO Thread
在InnoDB存储引擎中大量使用了AIO(AsyncIO)来处理写I0请求,这样可以极大提高数据库的性能。而IO Thread的工作主 ...
MySQL事务应用和原理
MySQL架构
网络连接层
客户端连接器(Client Connectors):提供与MySQL服务器建立的支持,它们通过各自API技术与MySQL建立连接。
服务层(MySQL Server)服务层是MySQL Server的核心,主要包含系统管理和控制工具、连接池、SQL接口、解析器、查询优化器和缓存六个部分。
1234561. 连接池(Connection Pool):负责存储和管理客户端与数据库的连接,一个线程负责管理一个连接。[官网性能测试报告:引入线程池,性能稳定性与性能会有很大得提升,128并发,读写模式, mysql高出60倍,只读18倍,若不引用线程池,线程创建关闭性能消耗大]2. 系统管理和控制工具(Management Services & Utilities):例如备份恢复、安全管理、集群管理等3. SQL接口(SQL Interface):用于接受客户端发送的各种SQL命令,并且返回用户需要查询的结果。比如DML、DDL、存储过程、视图、触发器等。4. 解析器(Parser):负责将请求的SQL解析生成一个"解析树" ...
CompletableFuture学习
前期准备12345678/** * 定义线程池 */public static ExecutorService service = Executors.newFixedThreadPool(5);private static String getThreadInfo() { return " 线程: " + Thread.currentThread().getName() + "_" + Thread.currentThread().getId();}
启动异步任务1、runAsync 无入参、无返回值
123456789101112131415/** * runAsync:无入参、无返回值 * Executor为空,则采用默认的ForkJoinPool.commonPool线程池,否则使用自定义的ThreadPool * @throws ExecutionException * @throws InterruptedException */private static void one() thro ...
Head First设计模式
设计模式入门OO基础
抽象、封装、多态、继承
OO原则
封装编号,
多用组合少用继承
针对接口编程,不针对实现编程
“针对接口编程”真正的意思是“针对超类型(supertype)编程”。
这里所谓的“接口”有多个含义,接口是一个“概念”,也是一种Java的interface构造。你可以在不涉及Java interface的情况下,“针对接口编程”,关键就在多态。利用多态,程序可以针对超类型编程,执行时会根据实际状况执行到真正的行为,不会被绑死在超类型的行为上。“针对超类型编程”这句话,可以更明确地说成“变量的声明类型应该是超类型,通常是一个抽象类或者是一个接口,如此,只要是具体实现此超类型的类所产生的对象,都可以指定给这个变量。这也意味着,声明类时不用理会以后执行时的真正对象类型!”
策略模式策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
应用示例,我们现在都有超类Duck,具有共同的特征会 ...
分布式工具类
分布式时间戳确保雪花Id唯一性的关键点就在于机器码。
Snowflake的机器码workerId默认由本机IP和进程Id计算得到,各取末尾5位移位后拼在一起。因此,局域网内不同机器,或者相同机器的不同进程,其机器码基本上不会相同。在多网段局域网,或者跨机房场景,机器码有一定可能性相同。机器码加入进程Id,避免某个应用在同一台服务器上多实例部署时得到相同workerId。如果要求绝对不相同的机器码,可通过手工设置唯一workerId的方式来实现。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.ThreadFactory;import jav ...
内存泄漏问题排查
线程池导致内存泄漏问题排查先看监控,现象很直接:老年代持续上涨,线程 Waiting 高到 3.6k。
接着 dump 堆内存。
1jmap -dump:live,format=b,file=heap.bin pid
重要服务先下线再 dump,不然 dump 期间接口可能抖动。容器服务可以先在 Nacos 下线实例再操作。
拿到 dump 文件后,用 IDEA Profiler 或 Eclipse MAT 分析。
先看 Leak Suspects,直接能看到线程对象占用异常。
再看大对象,Thread 数量已经到 1801。
继续顺着 GC 引用看,问题就落到线程池上了。
进容器跑 jstack 看线程快照:
12345678910111213141516171819202122232425"pool-663-thread-1" #113206 prio=5 os_prio=0 tid=0x00007f9b902df800 nid=0x1ba27 waiting on condition [0x00007f9ace5a4000] java. ...
Cassandra学习
安装1、下载
1打开官网,选择下载频道 https://cassandra.apache.org/download/
2、新建数据存储目录,data目录
123# 如果不配置数据目录默认为$CASSANDRA_HOME/data/data;data_file_directories: - D:\coding-software\apache-cassandra-3.11.11\data
3、新建日志目录,commitlog目录
123# 如果不配置日志目录,默认为:$CASSANDRA_HOME/data/commitlog;commitlog_directory: - D:\coding-software\apache-cassandra-3.11.11\commitlog
4、新建缓存目录,saved_caches目录
12# 如果不配置日志目录,默认为:$CASSANDRA_HOME/data/saved_caches;saved_caches_directory: D:\coding-software\apache-cassandra-3.11 ...



