1、打开设置面板:file -> setting -> Editor -> file and code Templates
选择其中的inclues选项卡,并选择File header,如图。不要选择Files选项卡再设置Class,这样比较麻烦,而且这样设置以后没新建一个类都要自己写一次Date。
2、在右边编辑面板插入自己想要的注释即可。其中${}是变量,需要在变量基本都在编辑款下面的Description,往下拉即可看到。
/* * @Classname ${NAME} * * @Date ${DATE} * * @userName */
3、新建一个类,看是否自动加了注释
二、方法注释
1、打开设置面板:file -> setting -> Editor -> Live Templates
2、新建一个Template Group…,命名随意,假设为bokeyuan,然后选择该组,点击新建一个模板Live Template
3、名称建议设为*,文本框输入自己想要设置的注释格式,右下角要选择enter(原本是tab)。
4、留意注释格式,其中参数要直接写变量$param$,开头只有一个*号。写好之后点击上图框中的edit variables
其中返回值return使用系统自带的,下拉可以找到methodReturnType()
5、自定义多行参数注释
IDEA自带的参数函数methodParameters()产出的注释格式是这样的:
/** * * @param [a,b,c] * @return void * @throws */
我们可能需要的是多行参数注释:
/** * * @param a * @param b * @param c * @return void * @throws */
这个时候就要使用里面的groovyScript()函数来自定义格式:
groovyScript("def result=''; def params=\"${_1}\".replaceAll('[\\\\[|\\\\]|\\\\s]', '').split(',').toList(); for(i = 0; i < params.size(); i++) {if(i == 0) result += '* @param ' + params[i] + ' ' + ((i < params.size() - 1) ? '\\n' : '');else result+=' * @param ' + params[i] + ' ' + ((i < params.size() - 1) ? '\\n' : '')}; return result", methodParameters())
直接复制在Expression里面即可。
6、选择语言,点击Define勾选Java
分库按照uid分为16个库,账户表不分表默认16张。每张表按照 1kw*16=1.6 亿个账户。
单表能存储多少要综合考虑,比如查询类型,单次查询的RT,冷热数据占比( innodb_buffer_pool 利用率)、是否充分发挥了索引,索引是否达到3星级别,
索引片
中没有经常变更的字段等。
账户流水表按照日期分表365张,流水数据会随着时间推移逐渐变成冷数据,定期归档冷数据。(这里约定了,流水查询只能按照uid+日期查询。如果运营类的需求,要横跨分片key获取,走OLAP方案 clickhouse、hive等)
分库分表采用阿里云分布式数据库产品DRDS,1个主库集群+2个读库集群(读库做了读负载均衡,可以按需扩容)。
既然用了DRDS分布式数据库产品,那么在查询上需要充分考虑分片键
的限制,如果存储和查询出现分片键冲突问题就需要我们手动计算分片路由,直接访问物理节点。
访问物理节点需要借助DRDS专用SQL注释
子句来完成。
先通过 show node
查看物理DB ID、show topology from logic_table_name
查看物理表ID,然后在SQL带上特定的注释子句
。
SELECT /*+TDDL:scan('logic_table_name', real_table=("real_table_name"),node='real_db_node_id')*/
count(1) FROM logic_table_name ;
账户更新: 对账户更新都有一个前提就是账户已经开通,但是我们为了最大化账户系统在使用上的便利性,让前台业务方不需要做初始化动作,由账户系统惰性初始化
,比如发现账户不存在就自动初始化账户数据。
但是我们怎么知道账户不存在,不可能每次都去查询一次或者根据执行返回错误判断。而且 update 语句是区分不了错误的 账户不存在 还是 余额不足 或者其他原因。
那么如何巧妙的解决这个问题,只要一次DB往返。
我们可以使用 Mysql INSERT INTO ... ON DUPLICATE KEY UPDATE ...
子句,但是该子句有一个限制就是不支持 where
子句。
-- cut_version 乐观锁、account_property 账户属性
insert into tb_account(uid,balance,cut_version,account_property) values("%s",%d,%d,%d) ON DUPLICATE KEY UPDATE balance = balance + %d,cut_version = cut_version+1
其实不完全推荐使用这个方法,因为这个方法也有弊端就是将来 where 子句无法使用,还有一个办法就是合并 账户查询 和 插入 为一条 sql 提交。
DB操作本身rt可能很短,但是如果跨网络那么事务的延迟会带来DB的串行化增加,降低并发度,整体应用 rt就会增加。所以一个原则就是尽量不要跨网络开事务,合并sql做一次事务提交,最短的事务周期,减少跨网络的事务操作,如果我们将单次事务网络交互减少2-3次,性能的提高可能会增加2-3倍,同样由于网络的不稳定抖动丢包对 999rt 线的影响也会减少2-3倍。
平衡好当前系统是
业务密集型
还是数据密集型
。
判断当前系统是否有很强的业务层逻辑,是否要运用DDD
、RUP
等强模型的工程方法。毕竟强模型
和高性能
在落地的时候有些方面是冲突的,需要进一步借助CRQS
、GRASP
等工程方法来解决。
单行热点问题: 单行的TPS都是串行的,事务rt越短TPS就越高,按照1ms计算,差不多TPS就是1000。一般只有机构账户
类型才会有这个需求。
我们可以将单行变成多行,增加行的并行度,加大账户操作的并发度。(这个方案要评估好写入和查询两端需求)
id | uid | balance | slot |
---|---|---|---|
1 | 10101010 | 1000 | 1 |
2 | 10101010 | 2000 | 2 |
3 | 10101010 | 3000 | 3 |
4 | 10101010 | 400 | 4 |
5 | 10101010 | 300 | 5 |
6 | 10101010 | 200 | 6 |
7 | 10101010 | 200 | 7 |
8 | 10101010 | 200 | 8 |
9 | 10101010 | 200 | 9 |
10 | 10101010 | 200 | 10 |
insert into tb_account (uid,balance,slot)
values(10101010, 1000, round(rand()*9)+1)
on duplicate key update balance=balance+values(balance)
这里的 10slot*单个slot 1000TPS,理论上可以跑到1w,如果机构账户数据量很大,可以扩展slot
个数。
账户的总余额通过sum()
汇总,如果业务场景中有余额的频繁sum()操作,可以通过增加余额中间表,定期 insert into tb_account_total select sum(balance) total_balance from tb_account group by uid
。
通常机构账户的结算是有周期的(T+7、T+30等),而且基本是没有并发,所以在账户余额扣减方面就可以轻松处理。
有两种实现方案:
第一种,账户余额允许单个slot为负数,但是总的sum()是正数。通过子查询来对余额进行检查
https://job.cnblogs.com/Enterprise/348334/
https://job.cnblogs.com/Offer/199760/
https://job.cnblogs.com/Offer/199761/
https://job.cnblogs.com/Offer/199762/
https://q.cnblogs.com/q/127949/
https://www.iqiyi.com/paopao/feed_158087696148.html
https://www.iqiyi.com/paopao/feed_158087482948.html
https://www.iqiyi.com/paopao/feed_158087050748.html