- 浏览: 1148116 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (138)
- JAVA基础 (22)
- Spring (6)
- 设计模式 (2)
- JDK源码 (3)
- java-功能组件 (4)
- 游戏项目 (2)
- linux (13)
- Oracle (2)
- struts (1)
- 字符集 (8)
- HTTP协议 (2)
- java-网络通信 (1)
- 工具软件推荐 (2)
- tomcat (1)
- java-容器框架 (2)
- java-IO框架 (2)
- java-多线程框架 (4)
- java-NIO框架 (0)
- jquery (2)
- 工具使用 (12)
- 加密解密 (1)
- redis (2)
- maven (2)
- svn (1)
- eclipse (1)
- mysql (11)
- 我的收藏 (1)
- JAVA进阶 (26)
- 运维 (3)
- protocol buffer (1)
- 优秀博主 (1)
- nginx (1)
- 算法 (2)
- 故障排查 (4)
- 粤语歌曲 (6)
- 生活总结 (6)
- 高并发 (4)
- 语言训练 (1)
- 读书笔记 (5)
- 诗歌 (1)
- tomcat源码学习 (1)
- 软件词汇 (1)
- git (1)
最新评论
-
ryuhi:
一个是来源source,一个是来源方序列号seq这两个数据要怎 ...
高并发的核心技术-幂等的实现方案 -
xuezhongyu01:
无量 写道Master-Gao 写道理论感觉还行,可以代码我还 ...
高并发的核心技术-幂等的实现方案 -
无量:
Master-Gao 写道理论感觉还行,可以代码我还是不会写。 ...
高并发的核心技术-幂等的实现方案 -
phil_jing:
@RequestParam 默认 true
SpringMVC注解@RequestParam全面解析 -
aguai0:
aguai0 写道第五条里的如果要获取任务执行结果,用Comp ...
JAVA进阶----ThreadPoolExecutor机制
系统开发中的坑
这个是在公司分享的一个ppt,整理下发到博客里,记录下,也是避免忘记了
一.幂等性
二.数据库
三.代码默认写法
四.业务设计
一、幂等性
概念
不管调用多少次,都应该产生一样的效果和返回一样的结果
案例:
1. 前端重复提交选中的数据,应该后台只产生对应这个数据的一个反应结果。
2. 我们发起一笔付款请求,应该只扣用户账户一次钱,当遇到网络重发或系统bug重发,也应该只扣一次钱
3. 发送消息,也应该只发一次,同样的短信发给用户,用户会哭的
4. 创建业务订单,一次业务请求只能创建一个,创建多个就会出大问题。
技术实现(一)
查询操作
查询一次和查询多次,在数据不变的情况下,查询结果是一样的。
select是天然的幂等操作。
技术实现(二)
删除操作
删除操作也是天生幂等的,删除一次和多次删除都是把数据删除。
(注意可能返回结果不一样,删除的数据不存在,返回0,删除的数据多条,返回结果多个)
Select * from table_xxxwhere id=#id;
不抛出异常,删除操作都返回true, 注意Dao层代码写法
技术实现(三)
唯一索引,防止新增脏数据
案例:
支付宝的资金账户,支付宝也有用户账户,每个用户只能有一个资金账户,怎么防止给用户创建资金账户多个,那么给资金账户表中的用户ID加唯一索引,所以一个用户新增成功一个资金账户记录要点:唯一索引或唯一组合索引来防止新增数据存在脏数据(当表存在唯一索引,并发新增报错时,再次调用接口会返回成功结果)
注意点:
先查询,用唯一索引来查,后新增,新增控制幂等
技术实现(四)
token机制,防止页面重复提交
业务要求:页面的数据只能被点击提交一次
发生原因:由于重复点击或者网络重发,或者nginx重发等情况会导致数据被重复提交
解决办法:集群环境:采用token加redis(redis单线程的,处理需要排队)单JVM环境:采用token加redis或token加jvm内存
处理流程:1. 数据提交前要向服务的申请token,token放到redis或jvm内存,token有效时间2. 提交后后台校验token,同时删除token,生成新的token返回
token特点:要申请,一次有效性,可以限流注意:redis要用删除操作来判断token,删除成功代表token校验通过,如果用select+delete来校验token,存在并发问题,不建议使用
技术实现(五)
悲观锁
获取数据的时候加锁获取,进行业务操作在提select * from table_xxxwhere id = 'xxx' for update;
建议使用悲观锁:账户一个人拥有,铜宝账户,积分账户,会员等级账户
不建议使用:产品份额账户。。。几百个人抢一个份额
注意:id字段一定是主键或者唯一索引,不然是锁表,会死人的悲观锁使用时一般伴随事务一起使用,数据锁定时间可能会很长,根据实际情况选用,数据库引擎要用Innodb,支持行锁
技术实现(六)
乐观锁
乐观锁只是在更新数据那一刻锁表,其他时间不锁表,所以相对于悲观锁,效率更高。乐观锁的实现方式多种多样可以通过version或者其他状态条件:
1. 通过版本号实现update table_xxxset name=#name#,version=version+1 where version=#version#
2. 通过条件限制update table_xxxset avai_amount=avai_amount-#subAmount# where avai_amount-#subAmount# >= 0
增加额外表来保证单条记录的幂等,一个用户一个幂等。
要求:avai_amount-#subAmount# >= 0 ,这个情景适合不用版本号,只更新是做数据安全校验,适合库存模型,扣份额和回滚份额,性能更高注意:乐观锁的更新操作,最好用主键或者唯一索引来更新,这样是行锁,否则更新时会锁表,上面两个sql改成下面的两个更好update table_xxxset name=#name#,version=version+1 where id=#id# and version=#version#update table_xxxset avai_amount=avai_amount-#subAmount# where id=#id# and avai_amount-#subAmount# >= 0
技术实现(七)
分布式锁,拿不到conn
还是拿插入数据的例子,如果是分布是系统,构建全局唯一索引比较困难,例如唯一性的字段没法确定,这时候可以引入分布式锁,通过第三方的系统(redis或zookeeper),在业务系统插入数据或者更新数据,获取分布式锁,然后做操作,之后释放锁,这样其实是把多线程并发的锁的思路,引入多多个系统,也就是分布式系统中得解决思路。要点:某个长流程处理过程要求不能并发执行,可以在流程执行之前根据某个标志(用户ID+后缀等)获取分布式锁,其他流程执行时获取锁就会失败,也就是同一时间该流程只能有一个能执行成功,执行完成后,释放分布式锁(分布式锁要第三方系统提供)
技术实现(八)
select + insert
并发不高的后台系统,或者一些任务JOB,为了支持幂等,支持重复执行,简单的处理方法是,先查询下一些关键数据,判断是否已经执行过,在进行业务处理,就可以了
注意:核心高并发流程不要用这种方法,每天只执行几次的任务,建议使用,性能好一点
技术实现(九)
状态机幂等
在设计单据相关的业务,或者是任务相关的业务,肯定会涉及到状态机(状态变更图),就是业务单据上面有个状态,状态在不同的情况下会发生变更,一般情况下存在有限状态机,这时候,如果状态机已经处于下一个状态,这时候来了一个上一个状态的变更,理论上是不能够变更的,这样的话,保证了有限状态机的幂等。
注意:订单等单据类业务,存在很长的状态流转,一定要深刻理解状态机,对业务系统设计能力提高有很大帮助
技术实现(十)
对外提供接口的api如何保证幂等
如银联提供的付款接口:需要接入商户提交付款请求时附带:source来源,seq序列号source+seq在数据库里面做唯一索引,防止多次付款,(并发时,只能处理一个请求)
重点:对外提供接口为了支持幂等调用,接口有两个字段必须传,一个是来源source,一个是来源方序列号seq,这个两个字段在提供方系统里面做联合唯一索引,这样当第三方调用时,先在本方系统里面查询一下,是否已经处理过,返回相应处理结果;没有处理过,进行相应处理,返回结果。注意,为了幂等友好,一定要先查询一下,是否处理过该笔业务,不查询直接插入业务系统,会报错,但实际已经处理了。
二、数据库
数据库设计原则
字段的命名规范化,简洁易懂,cash—取现,不合理,withdraw合理些
字段名要有注释,方便后人(不是死了的)查找问题
主键是选择自增的方式,还是带业务含义的主键,还是一个自增方式主键+ 一个业务含义流水要考虑清楚
字段长度选择,字符串考虑未来扩展性问题,整形有很多种,int(11)和int(2),在性能上并没有优化
数据库引擎选择innodb
是否有幂等性业务需求靠数据库唯一索引来完成,索引设置的合理性
Decimal的长度选择,保留小数点后6位
同一个系统中各个表中同样含义的字段,名词要一致hk_detail,,HkDetail
同一个系统前缀一致,tb_share,tb_income_expense, tbShareId, shareId其他表里面存储的(MBA智库百科,查询金融词汇)
主键的设计
每个表都应该设置一个ID主键,最好的是一个INT型,并且设置上自动增加的AUTO_INCREMENT标志,这点其实应该作为设计表结构的第一件必然要做的事!!
个人强烈建议:自增id主键+全局唯一序列号
100xxxxxx-广东省, 200xxxxxx-黑龙江
遍历需求的对于自增ID的表来说很容易实现
主键设计:
1.自增
2.15位时间戳+业务标志+rand 32
3.分布式全局唯一,UUID或额外系统主键生成系统支持
数据库字段长度的优化
类型
占用字节
范围
tinyint 1 -128~127
smallint 2 -32768~32767
mediumint 3 -8388608~8388607)
int 4 -2147483648~2147483647
bigint 8 +-9.22*10的18次方
原则:
不浪费空间, 能用小的数据类型干嘛占用那么多空间
方便以后扩容
能用int,不影响业务理解,不用char
Tinyint(30)------30个字节---10, 000000000000000000010,
例子
direction收支方向,就收和支两个值,一定用tinyint(1)
数据库表名的命名
原则:
同一个应用都相同前缀,如tbj_aaa,tbj_bbb
简洁,见名知意
数据库字段的命名
原则:
同一个含义的字段各个表中名称一致
尽量用专业词汇
简洁,见名知意
例子
持仓的专业词汇是position,份额是share,所以份额表示tb_share
用户份额id,没有用tb_share_id而是用share_id,简洁易懂
设计索引
原则:
根据业务需求设计索引
索引不要过多,影响插入更新性能
如果有幂等性需求,设置数据库唯一索引
例子
如铜板账户,userId设置为唯一索引,一个人只能有一个铜板账户
收支流水表的userID设置普通索,查询效率高
Create_time默认加索引。。。。
A,b,c组合索引,,A**,ABX XXB XXC, a+b+c, 按位加索引
字段类型的选择
原则:
整形效率高于字符串,高于datetime
时间long形式时间建议加
日期:int20121212,2100000 2010000
长度过程用text,remark,varchar1024,默认截取,前端,append,/n
如果表数据量很大,主键用bigint
例子
occur_date用整形不用datetime,20121212,查询频繁用整形效率高
因为每个表未来的数据量都会很大,用bigint
如何避免全表扫描,如何避免误删数据
原则:
全表扫描会造成数据库挂掉,OOM
索引值很少,走索引也会全表扫描
删数据时,加limit限制和where后必须有条件
例子
DAO层面限制不走索引的查询sql
DAO层面限制索引值少的查询sql
Delete from tb_positionwhere id=142343 limit 1;
怎么分表?
深入理解业务,根据业务特性来分表,根据查询需求来分表
案例:
1.代金券分表(季度分)
2.每日收益分表(userId取余)
3.对账分表(按月分)
4.微信红包分表(年度+用户分)
分表后怎么查询?
前端要配合改,尽量不支持后台聚合查询
案例:
I.微信红包查询收支明细, 只能按年查询
II.按月查询
III.查询历史等
缓存和DB数据一致
索引字段上进行运算会使索引失效
尽量避免在WHERE子句中对字段进行函数或表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
SELECT * FROM T1 WHERE F1/2=100 应改为: SELECT * FROM T1 WHERE F1=100*2
禁止如下sql:
Select * from table_xxxwhere nvl(filed_xx)=xxx;(红色字体不能加函数)
Sql的编写
一个xml里不要有两个表名,不做关联表查询,因为mysql接不了那么多客
下面的写法不对,不要给字段加函数
Sql通用查询的优化
Sql1:
select * from coupon where status=1 and use_time>’2016-03-14 00:00:00’ and use_time<’2016-03-15 00:00:00’;
Sql2:
select * from coupon where use_time>’2016-03-14 00:00:00’ and use_time<’2016-03-15 00:00:00’and status=1;
默认前提:
status,use_time都是索引字段
由于where后面索引一般生效顺序是从前到后,所以sql1是先走索引status再走use_time,sql2是先走索引use_time,后走status。
优化手段:先走的索引影响条数越少越好
三、代码默认写法
如何保证小数点后计算准确性
1.保留两位有效数字的值,要保留小数点后六位BigDecimal进行计算
案例:
非标产品收益
2. 保留六位有效数字的值,要保留小数点后20位BigDecimal进行计算
案例:
铜宝账户
SimpleDateFormat不是线程安全的
每次要new,不new,原因都查不到
如何避免全表扫描和误删数据—DAO层就禁止掉
日志是为了查问题,所以怎么记日志?
用户ID,异常原因这是必须要记录的,其他的业务关键信息也要记录下来
核心业务流程,请求参数,执行完业务影响数据要记录下来,info日志
核心业务流程,执行时间要记录下来,info日志
一个类中每条日志都要是唯一的,不然你怎么知道是那块代码出来的日志
日志要漂亮,要格式化,打印出来的才漂亮
案例:
出问题了可不可以立即关掉,开关?
核心业务系统要有开关,重大异常时可以随时关掉,,服务降级
案例:
交易系统全局开关,新手体验金开关
只用一次的系统,单独开发,独立部署
一些促销活动和营销活动临时开发,要临时部署,不要影响主业务系统
案例:
支付宝5福
15年春晚微信摇一摇
activity
经常扩展的常量类用java类不用枚举
枚举在增加变量,新老版本,序列化,反序列化中不太友好
JOB什么标准?
支持重复执行,幂等,这是基础
F(x),F(Y) 是两个幂等操作:所以:f(x) +f(y)也是幂等的
JOB跑一半断电了,支持重跑修复
JOB返回结果要有,查询多少数据,处理了多少,失败了多少,成功了多少
JOB执行时间比较久的,继承AbstractJob来写,支持中断, sorce->trade>
几个JOB之间应该是互斥关系,可以独立跑,不要搞依赖
代码看着要美丽,漂亮
不要有黄点提示
不要用deprecate的方法和类,慢慢改掉
特别长的方法名,类名不漂亮
代码块是个方块,一行不要超一屏幕,横着拉代码太难看
竖着不要超过一屏幕,一个原理
嵌套不要超过三层,看不懂
一句话解决的,不要写一堆。啰嗦,多用apache工具类
代码看着要有结构感觉,不要不换行
注释要点睛
一个流程多次用到的数据,提前放内存
一些DB的配置数据,dubbo调用的获取的需要多次使用的数据等
查询一次,放到内存,多次使用,不用每次用到再去查询
敏感信息,加密
身份证,姓名,银行卡号,密码等核心数据,存储时要加密存储
看业务需求,哪些字段还需要加密
考虑加密算法的性能
RSA < DES < AES < MD5
MD5----》签名----》完整性,正确性
RSA----》加密----》安全性
加密算法的安全性
看复杂度选择,一般和性能成反比
去掉过多的if else
改成键值对配置形式,取配置便于维护,配置的选择看情况
数据库、应用、前端、含义的一致性
一个含义的字段,要用一个英文单词,别多个英文单词一个含义,搞死人的
怎么做遍历?
有自增主键的遍历
select * from table_xxxwhere status = #status and limit 1000; id > #lastQueryId
优点:性能高,不漏数据,遍历数据状态变更不会造成位移
缺点:暂时没发现
非自增主键遍历
select * from table_xxxwhere status = #status and id > #lastQueryIdlimit 1000;
每次取出最后一条ID,进行下一次查询,性能极高,强哥推荐,好片
是否是带状态更新的遍历:
会可能存在位移差,存在漏数据
解决办法:
1. id>#lastId, limit 100, order没有自增主键
2. Create_time索引,create_time>=#lastCreateTime, limit 100;支持幂等
3. 存在新增数据的遍历,做临时表,临时表做业务重复判断。
4. create_time半开查询create_time>= egtCreateTimeand create_time<ltCreateTime
容错
异步怎么做?
同步怎么做,超时时间?
对方接口的承受能力?
容错代码是正常代码的2倍以上?
doPay,,,,超时了,,,但是它成功了。。。。反查。。。。
一眼看的懂。一眼看不懂,一定有问题
一眼看不懂,怎么维护
一眼看不懂是流程设计问题还是命名问题,反正是有问题的
业务领域也是,很清晰,看得懂
四、业务设计
怎样做重构?
复杂简单化
简单标准化
标准流程化
流程自动化
做成一个标准的模式,大家都认为这么做合理,这事就成了
案例:交易流程,充值流程,做成品牌
根据状态机设计业务
业务核心点
业务边界点
业务对接点
核心业务状态机
服务升降级
服务自动升降级
案例:
铜板街交易核心汇总,铜宝系统,卡券,可以挂。挂掉不影响交易
这个是在公司分享的一个ppt,整理下发到博客里,记录下,也是避免忘记了
一.幂等性
二.数据库
三.代码默认写法
四.业务设计
一、幂等性
概念
不管调用多少次,都应该产生一样的效果和返回一样的结果
案例:
1. 前端重复提交选中的数据,应该后台只产生对应这个数据的一个反应结果。
2. 我们发起一笔付款请求,应该只扣用户账户一次钱,当遇到网络重发或系统bug重发,也应该只扣一次钱
3. 发送消息,也应该只发一次,同样的短信发给用户,用户会哭的
4. 创建业务订单,一次业务请求只能创建一个,创建多个就会出大问题。
技术实现(一)
查询操作
查询一次和查询多次,在数据不变的情况下,查询结果是一样的。
select是天然的幂等操作。
技术实现(二)
删除操作
删除操作也是天生幂等的,删除一次和多次删除都是把数据删除。
(注意可能返回结果不一样,删除的数据不存在,返回0,删除的数据多条,返回结果多个)
Select * from table_xxxwhere id=#id;
不抛出异常,删除操作都返回true, 注意Dao层代码写法
技术实现(三)
唯一索引,防止新增脏数据
案例:
支付宝的资金账户,支付宝也有用户账户,每个用户只能有一个资金账户,怎么防止给用户创建资金账户多个,那么给资金账户表中的用户ID加唯一索引,所以一个用户新增成功一个资金账户记录要点:唯一索引或唯一组合索引来防止新增数据存在脏数据(当表存在唯一索引,并发新增报错时,再次调用接口会返回成功结果)
注意点:
先查询,用唯一索引来查,后新增,新增控制幂等
技术实现(四)
token机制,防止页面重复提交
业务要求:页面的数据只能被点击提交一次
发生原因:由于重复点击或者网络重发,或者nginx重发等情况会导致数据被重复提交
解决办法:集群环境:采用token加redis(redis单线程的,处理需要排队)单JVM环境:采用token加redis或token加jvm内存
处理流程:1. 数据提交前要向服务的申请token,token放到redis或jvm内存,token有效时间2. 提交后后台校验token,同时删除token,生成新的token返回
token特点:要申请,一次有效性,可以限流注意:redis要用删除操作来判断token,删除成功代表token校验通过,如果用select+delete来校验token,存在并发问题,不建议使用
技术实现(五)
悲观锁
获取数据的时候加锁获取,进行业务操作在提select * from table_xxxwhere id = 'xxx' for update;
建议使用悲观锁:账户一个人拥有,铜宝账户,积分账户,会员等级账户
不建议使用:产品份额账户。。。几百个人抢一个份额
注意:id字段一定是主键或者唯一索引,不然是锁表,会死人的悲观锁使用时一般伴随事务一起使用,数据锁定时间可能会很长,根据实际情况选用,数据库引擎要用Innodb,支持行锁
技术实现(六)
乐观锁
乐观锁只是在更新数据那一刻锁表,其他时间不锁表,所以相对于悲观锁,效率更高。乐观锁的实现方式多种多样可以通过version或者其他状态条件:
1. 通过版本号实现update table_xxxset name=#name#,version=version+1 where version=#version#
2. 通过条件限制update table_xxxset avai_amount=avai_amount-#subAmount# where avai_amount-#subAmount# >= 0
增加额外表来保证单条记录的幂等,一个用户一个幂等。
要求:avai_amount-#subAmount# >= 0 ,这个情景适合不用版本号,只更新是做数据安全校验,适合库存模型,扣份额和回滚份额,性能更高注意:乐观锁的更新操作,最好用主键或者唯一索引来更新,这样是行锁,否则更新时会锁表,上面两个sql改成下面的两个更好update table_xxxset name=#name#,version=version+1 where id=#id# and version=#version#update table_xxxset avai_amount=avai_amount-#subAmount# where id=#id# and avai_amount-#subAmount# >= 0
技术实现(七)
分布式锁,拿不到conn
还是拿插入数据的例子,如果是分布是系统,构建全局唯一索引比较困难,例如唯一性的字段没法确定,这时候可以引入分布式锁,通过第三方的系统(redis或zookeeper),在业务系统插入数据或者更新数据,获取分布式锁,然后做操作,之后释放锁,这样其实是把多线程并发的锁的思路,引入多多个系统,也就是分布式系统中得解决思路。要点:某个长流程处理过程要求不能并发执行,可以在流程执行之前根据某个标志(用户ID+后缀等)获取分布式锁,其他流程执行时获取锁就会失败,也就是同一时间该流程只能有一个能执行成功,执行完成后,释放分布式锁(分布式锁要第三方系统提供)
技术实现(八)
select + insert
并发不高的后台系统,或者一些任务JOB,为了支持幂等,支持重复执行,简单的处理方法是,先查询下一些关键数据,判断是否已经执行过,在进行业务处理,就可以了
注意:核心高并发流程不要用这种方法,每天只执行几次的任务,建议使用,性能好一点
技术实现(九)
状态机幂等
在设计单据相关的业务,或者是任务相关的业务,肯定会涉及到状态机(状态变更图),就是业务单据上面有个状态,状态在不同的情况下会发生变更,一般情况下存在有限状态机,这时候,如果状态机已经处于下一个状态,这时候来了一个上一个状态的变更,理论上是不能够变更的,这样的话,保证了有限状态机的幂等。
注意:订单等单据类业务,存在很长的状态流转,一定要深刻理解状态机,对业务系统设计能力提高有很大帮助
技术实现(十)
对外提供接口的api如何保证幂等
如银联提供的付款接口:需要接入商户提交付款请求时附带:source来源,seq序列号source+seq在数据库里面做唯一索引,防止多次付款,(并发时,只能处理一个请求)
重点:对外提供接口为了支持幂等调用,接口有两个字段必须传,一个是来源source,一个是来源方序列号seq,这个两个字段在提供方系统里面做联合唯一索引,这样当第三方调用时,先在本方系统里面查询一下,是否已经处理过,返回相应处理结果;没有处理过,进行相应处理,返回结果。注意,为了幂等友好,一定要先查询一下,是否处理过该笔业务,不查询直接插入业务系统,会报错,但实际已经处理了。
二、数据库
数据库设计原则
字段的命名规范化,简洁易懂,cash—取现,不合理,withdraw合理些
字段名要有注释,方便后人(不是死了的)查找问题
主键是选择自增的方式,还是带业务含义的主键,还是一个自增方式主键+ 一个业务含义流水要考虑清楚
字段长度选择,字符串考虑未来扩展性问题,整形有很多种,int(11)和int(2),在性能上并没有优化
数据库引擎选择innodb
是否有幂等性业务需求靠数据库唯一索引来完成,索引设置的合理性
Decimal的长度选择,保留小数点后6位
同一个系统中各个表中同样含义的字段,名词要一致hk_detail,,HkDetail
同一个系统前缀一致,tb_share,tb_income_expense, tbShareId, shareId其他表里面存储的(MBA智库百科,查询金融词汇)
主键的设计
每个表都应该设置一个ID主键,最好的是一个INT型,并且设置上自动增加的AUTO_INCREMENT标志,这点其实应该作为设计表结构的第一件必然要做的事!!
个人强烈建议:自增id主键+全局唯一序列号
100xxxxxx-广东省, 200xxxxxx-黑龙江
遍历需求的对于自增ID的表来说很容易实现
主键设计:
1.自增
2.15位时间戳+业务标志+rand 32
3.分布式全局唯一,UUID或额外系统主键生成系统支持
数据库字段长度的优化
类型
占用字节
范围
tinyint 1 -128~127
smallint 2 -32768~32767
mediumint 3 -8388608~8388607)
int 4 -2147483648~2147483647
bigint 8 +-9.22*10的18次方
原则:
不浪费空间, 能用小的数据类型干嘛占用那么多空间
方便以后扩容
能用int,不影响业务理解,不用char
Tinyint(30)------30个字节---10, 000000000000000000010,
例子
direction收支方向,就收和支两个值,一定用tinyint(1)
数据库表名的命名
原则:
同一个应用都相同前缀,如tbj_aaa,tbj_bbb
简洁,见名知意
数据库字段的命名
原则:
同一个含义的字段各个表中名称一致
尽量用专业词汇
简洁,见名知意
例子
持仓的专业词汇是position,份额是share,所以份额表示tb_share
用户份额id,没有用tb_share_id而是用share_id,简洁易懂
设计索引
原则:
根据业务需求设计索引
索引不要过多,影响插入更新性能
如果有幂等性需求,设置数据库唯一索引
例子
如铜板账户,userId设置为唯一索引,一个人只能有一个铜板账户
收支流水表的userID设置普通索,查询效率高
Create_time默认加索引。。。。
A,b,c组合索引,,A**,ABX XXB XXC, a+b+c, 按位加索引
字段类型的选择
原则:
整形效率高于字符串,高于datetime
时间long形式时间建议加
日期:int20121212,2100000 2010000
长度过程用text,remark,varchar1024,默认截取,前端,append,/n
如果表数据量很大,主键用bigint
例子
occur_date用整形不用datetime,20121212,查询频繁用整形效率高
因为每个表未来的数据量都会很大,用bigint
如何避免全表扫描,如何避免误删数据
原则:
全表扫描会造成数据库挂掉,OOM
索引值很少,走索引也会全表扫描
删数据时,加limit限制和where后必须有条件
例子
DAO层面限制不走索引的查询sql
DAO层面限制索引值少的查询sql
Delete from tb_positionwhere id=142343 limit 1;
怎么分表?
深入理解业务,根据业务特性来分表,根据查询需求来分表
案例:
1.代金券分表(季度分)
2.每日收益分表(userId取余)
3.对账分表(按月分)
4.微信红包分表(年度+用户分)
分表后怎么查询?
前端要配合改,尽量不支持后台聚合查询
案例:
I.微信红包查询收支明细, 只能按年查询
II.按月查询
III.查询历史等
缓存和DB数据一致
索引字段上进行运算会使索引失效
尽量避免在WHERE子句中对字段进行函数或表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
SELECT * FROM T1 WHERE F1/2=100 应改为: SELECT * FROM T1 WHERE F1=100*2
禁止如下sql:
Select * from table_xxxwhere nvl(filed_xx)=xxx;(红色字体不能加函数)
Sql的编写
一个xml里不要有两个表名,不做关联表查询,因为mysql接不了那么多客
下面的写法不对,不要给字段加函数
Sql通用查询的优化
Sql1:
select * from coupon where status=1 and use_time>’2016-03-14 00:00:00’ and use_time<’2016-03-15 00:00:00’;
Sql2:
select * from coupon where use_time>’2016-03-14 00:00:00’ and use_time<’2016-03-15 00:00:00’and status=1;
默认前提:
status,use_time都是索引字段
由于where后面索引一般生效顺序是从前到后,所以sql1是先走索引status再走use_time,sql2是先走索引use_time,后走status。
优化手段:先走的索引影响条数越少越好
三、代码默认写法
如何保证小数点后计算准确性
1.保留两位有效数字的值,要保留小数点后六位BigDecimal进行计算
案例:
非标产品收益
2. 保留六位有效数字的值,要保留小数点后20位BigDecimal进行计算
案例:
铜宝账户
SimpleDateFormat不是线程安全的
每次要new,不new,原因都查不到
如何避免全表扫描和误删数据—DAO层就禁止掉
日志是为了查问题,所以怎么记日志?
用户ID,异常原因这是必须要记录的,其他的业务关键信息也要记录下来
核心业务流程,请求参数,执行完业务影响数据要记录下来,info日志
核心业务流程,执行时间要记录下来,info日志
一个类中每条日志都要是唯一的,不然你怎么知道是那块代码出来的日志
日志要漂亮,要格式化,打印出来的才漂亮
案例:
出问题了可不可以立即关掉,开关?
核心业务系统要有开关,重大异常时可以随时关掉,,服务降级
案例:
交易系统全局开关,新手体验金开关
只用一次的系统,单独开发,独立部署
一些促销活动和营销活动临时开发,要临时部署,不要影响主业务系统
案例:
支付宝5福
15年春晚微信摇一摇
activity
经常扩展的常量类用java类不用枚举
枚举在增加变量,新老版本,序列化,反序列化中不太友好
JOB什么标准?
支持重复执行,幂等,这是基础
F(x),F(Y) 是两个幂等操作:所以:f(x) +f(y)也是幂等的
JOB跑一半断电了,支持重跑修复
JOB返回结果要有,查询多少数据,处理了多少,失败了多少,成功了多少
JOB执行时间比较久的,继承AbstractJob来写,支持中断, sorce->trade>
几个JOB之间应该是互斥关系,可以独立跑,不要搞依赖
代码看着要美丽,漂亮
不要有黄点提示
不要用deprecate的方法和类,慢慢改掉
特别长的方法名,类名不漂亮
代码块是个方块,一行不要超一屏幕,横着拉代码太难看
竖着不要超过一屏幕,一个原理
嵌套不要超过三层,看不懂
一句话解决的,不要写一堆。啰嗦,多用apache工具类
代码看着要有结构感觉,不要不换行
注释要点睛
一个流程多次用到的数据,提前放内存
一些DB的配置数据,dubbo调用的获取的需要多次使用的数据等
查询一次,放到内存,多次使用,不用每次用到再去查询
敏感信息,加密
身份证,姓名,银行卡号,密码等核心数据,存储时要加密存储
看业务需求,哪些字段还需要加密
考虑加密算法的性能
RSA < DES < AES < MD5
MD5----》签名----》完整性,正确性
RSA----》加密----》安全性
加密算法的安全性
看复杂度选择,一般和性能成反比
去掉过多的if else
改成键值对配置形式,取配置便于维护,配置的选择看情况
数据库、应用、前端、含义的一致性
一个含义的字段,要用一个英文单词,别多个英文单词一个含义,搞死人的
怎么做遍历?
有自增主键的遍历
select * from table_xxxwhere status = #status and limit 1000; id > #lastQueryId
优点:性能高,不漏数据,遍历数据状态变更不会造成位移
缺点:暂时没发现
非自增主键遍历
select * from table_xxxwhere status = #status and id > #lastQueryIdlimit 1000;
每次取出最后一条ID,进行下一次查询,性能极高,强哥推荐,好片
是否是带状态更新的遍历:
会可能存在位移差,存在漏数据
解决办法:
1. id>#lastId, limit 100, order没有自增主键
2. Create_time索引,create_time>=#lastCreateTime, limit 100;支持幂等
3. 存在新增数据的遍历,做临时表,临时表做业务重复判断。
4. create_time半开查询create_time>= egtCreateTimeand create_time<ltCreateTime
容错
异步怎么做?
同步怎么做,超时时间?
对方接口的承受能力?
容错代码是正常代码的2倍以上?
doPay,,,,超时了,,,但是它成功了。。。。反查。。。。
一眼看的懂。一眼看不懂,一定有问题
一眼看不懂,怎么维护
一眼看不懂是流程设计问题还是命名问题,反正是有问题的
业务领域也是,很清晰,看得懂
四、业务设计
怎样做重构?
复杂简单化
简单标准化
标准流程化
流程自动化
做成一个标准的模式,大家都认为这么做合理,这事就成了
案例:交易流程,充值流程,做成品牌
根据状态机设计业务
业务核心点
业务边界点
业务对接点
核心业务状态机
服务升降级
服务自动升降级
案例:
铜板街交易核心汇总,铜宝系统,卡券,可以挂。挂掉不影响交易
发表评论
-
区块链!每个人都要了解下--十分钟洞见区块链的前世今生
2018-04-27 12:32 803区块链!每个人都要了解下--十分钟洞见区块链的前世今生 ... -
区块链!每个人都要了解下--十分钟洞见区块链的前世今生
2018-04-27 12:09 0为啥要讲区块链呢,因为它太火了,火到什么程度呢 ... -
项目打包,报软件包、类不存在问题排查过程
2017-05-16 17:13 5989项目打包报,软件包、类不存在问题排查过程 一、背景 ... -
海量数据存储--分库分表策略详解
2017-04-12 19:59 7337海量数据存储--分库分表策略详解 一、背景: 系统刚 ... -
jstack详解
2017-02-17 11:15 1918jstack http://www.open-open.co ... -
jdk-源码中的一些坑
2017-02-13 15:17 1254jdk-源码中的一些坑 1. Runnable接口的命名简直 ... -
金融的逻辑1--读书笔记
2017-02-08 23:26 1468过年在家读了一本书, ... -
git 使用 配置key
2016-12-29 10:55 1309转http://blog.sina.com.cn/s/ ... -
一次mysql死锁的排查过程
2016-11-21 10:04 11335一次mysql死锁的排查过程 一、背景 17号晚上要吃饭 ... -
JVM调优:选择合适的GC collector (三)
2016-11-15 20:51 1275CMS Collector 在很多地方,CMS Collec ... -
JVM调优:选择合适的GC collector (二)
2016-11-15 20:47 1001http://blog.csdn.net/historya ... -
JVM调优:选择合适的GC collector (一)
2016-11-15 20:45 1276http://blog.csdn.net/historyas ... -
jstat查看gc情况
2016-11-10 10:11 2498jps(Java Virtual Machine Proces ... -
tomcat源码学习(一) eclipse导入tomcat源码
2016-10-31 20:05 14161. 到官网下载Tomcat源代码,这里用到的是apache- ... -
深入分析ClassLoader
2016-10-27 23:27 786转(原文http://blog.csdn.net/xya ... -
业务架构模板
2016-10-20 19:56 1908业务架构模板 默认一个高大上的业务系统需要具备的技术点和对应 ... -
如何写一个强壮的JOB任务
2016-10-18 15:00 3019如何写一个强壮的JOB任务 1. JOB跑一半断电了,不能产 ... -
mybatis.xml中sql编写规范
2016-10-18 14:54 6262一、越少的代码,越强悍的功能,xml里面应该6个sql语句就够 ... -
数据库设计规范
2016-10-17 23:29 65861. 数据库设计基本规范 领域驱动表内容 ... -
全局主键生成器-支持单JVM1秒近1000万订单生成
2016-05-03 20:46 5683全局主键生成器 介绍: 相对于DB自增序列的全局主键生成器, ...
相关推荐
3. 结合ANSYS软件的功能:文章强调了通过UG软件和ANSYS软件集成来完成薄壁微坑缸套CAD系统开发。ANSYS是一个多功能的有限元分析软件,广泛应用于多个工业领域,如核工业、航空航天等。在CAD系统中集成ANSYS软件能够...
软件系统开发解决方案模板,留档备用。有喜欢的可以拖走拖走。。。。资源分现在都最低必须2分了。坑。。。。
《人月神话》中提到的“焦油坑”比喻,形象地描绘了软件项目中常见的困境,即投入更多的人力并不一定能解决问题,反而可能导致问题更加复杂。软件危机的主要特征表现为开发周期延长、成本超出预算以及难以保证软件...
在开发过程中,开发者还可能遇到的“坑”包括: - 网络安全问题:未加密的通信可能暴露敏感信息,需要确保数据传输的安全性。 - 并发处理:当处理大量设备或请求时,需要考虑并发控制,防止资源冲突。 - 设备兼容性...
Win10安装Linux子系统: 目前应用商店为win10 提供了多款Linux发行版本,其中包括Ubuntu、Debian、OpenSUSE等 这里我主要以Ubuntu系统为例: 第一步:点击“”设置图标“”,如下图所示 第二步:点击“更新和安全”...
标题中的“那些storm的坑坑”暗示了这篇文章可能主要讨论Apache Storm使用过程中遇到的问题和挑战。Apache Storm是一个开源的分布式实时计算系统,常用于实时数据流处理,它允许开发者连续处理无限的数据流。由于...
“撞击坑提取工具”正是针对ArcGIS平台开发的插件,它的核心功能在于从高分辨率遥感图像或数字地形模型(DTM)中自动检测并提取撞击坑。这个工具利用了先进的图像处理和模式识别技术,能有效地识别出那些由陨石撞击...
系统的设计测试结果表明,该电梯底坑进水监测及预警系统能够满足实际使用中的各项要求。系统的成功研发和应用,不仅提高了电梯安全使用的可靠性,减少了因电梯底坑积水造成的安全隐患和财产损失,同时也为类似的安全...
在实际项目开发过程中,DDD往往会被提及,但其实践过程中存在许多难以察觉的问题。本文将详细介绍在实施DDD时可能会遇到的问题,以便开发者能够避免这些“坑”。 首先,DDD强调的是领域建模,它基于模型驱动的原则...
软件开发设计:PHP、QT、应用软件开发、系统软件开发、移动应用开发、网站开发C++、Java、python、web、C#等语言的项目开发与学习资料 硬件与设备:单片机、EDA、proteus、RTOS、包括计算机硬件、服务器、网络设备、...
致远产品客开,对接其他门户系统开发的一个取数据接口示例,只适合致远产品开发的人员使用,上传此次文件也只为了记录成长经验,同时附上相对应代码
实用技巧与填坑篇会分享一些开发中的实用技巧,以及在开发过程中遇到的常见问题和解决方案。这些技巧和解决方案往往是开发者在实际开发过程中积累的经验。 Flutter的混合开发打包Android篇和iOS篇则是讲述如何将...
软件开发设计:PHP、QT、应用软件开发、系统软件开发、移动应用开发、网站开发C++、Java、python、web、C#等语言的项目开发与学习资料 硬件与设备:单片机、EDA、proteus、RTOS、包括计算机硬件、服务器、网络设备、...
3. 针对开发中常见的坑,如热重载(HotReload)、调试技巧等进行了解释和解决策略。 四、Redux、主题、国际化 1. 引入了Redux状态管理框架,解释了如何在Flutter中集成和使用Redux进行应用状态管理。 2. 讨论了...
在当今的互联网时代,电子商务已经成为不可或缺的一部分,而Asp.Net作为微软公司推出的一种强大的Web应用程序开发框架,因其高效、稳定和易于维护的特点,在电商系统开发中备受青睐。本篇将深入探讨一个基于Asp.Net...
海康威视作为全球领先的安防产品及解决方案提供商,其web3.0开发包是一个专为开发者设计的工具,旨在帮助用户构建基于Web的监控系统,实现远程访问、控制和管理海康威视的设备。这个开发包是海康威视在Web技术上的...
该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行! 1. 技术组成 前端:Vue/JSP/React/HTML+JS+CSS/ASP 后台框架代码:java/c/c++/...
该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行! 1. 技术组成 前端:Vue/JSP/React/HTML+JS+CSS/ASP 后台框架代码:java/c/c++/...
今天,我们就来探讨一下MIUI系统中关于通知类短信权限的那些问题以及如何巧妙地绕过这些“坑”。 首先,我们需要明确MIUI通知类短信权限的概念。在Android中,短信权限(READ_SMS)用于读取短信内容,这对于许多...
该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行! 1. 技术组成 前端:html、javascript、Vue 后台框架:SpringBoot 开发环境:idea 数据库...