2017年10月6日に書かれました
背景:プロジェクトのクリア処理、システムはFTPへのトランザクションデータとアップロードの全額の日々の営業日を生成し、FTPからファイルを取得するために、取引決済手続き後の分析データは、水を流す資金のバランス変更操作や登録を行います。
第1の車輪の圧力測定結果:TPS = 3
単一のシリアル処理を、ソース発見を分析靴を現像した後に、簡略化されたコア・コードは次の通りであります:
//遍历每条交易数据
foreach(){
insertLogAndUpdateBalance();
}
//启用事务
insertLogAndUpdateBalance(){
//插入资金流水
insertLog();
//更新余额
updateBalance();
}
最初のラウンドの改良された方法:
シリアルマルチプロセス単一のシリアルプロセスペンに変更1、
すなわちバック非同期リフレッシュバランス表に次いで水テーブルの残高に入金、及び図2に示すように、バランスの変化更新スイッチインサート
3は、ここで新たな問題を紹介します:どのようにバランスを負として控除されていないことを確認するには?プレゼンテーションから他の背後にある問題。
簡素化されたコアコード
//遍历每批交易数据,每500条一批
foreachBatch(){
insertLogAndUpdateBalanceBatch();
}
//启用事务
insertLogAndUpdateBalance(){
//插入资金流水
insertLogBatch();
//更新余额
updateBalanceBatch();
}
第2の車輪の圧力測定結果:TPS 15の間不安定である - 45
第二ラウンドの改良された方法:
タスクのタイミングを排除する方法を見つけるために開発した後、(SpringBootアイテム)
@EnableScheduling
public class ExceptionStatusChangeNotifyScheduler {
@Scheduled(cron = "0 */1 * * * ?")
public void doUpdateStatus() {
//业务逻辑处理
}
}
TPSは非常に不安定な現象になりますなぜ、これも説明して同時に、タスクを時限デフォルトは単一のスレッドを使用することで、非常に明確に説明されているクラスの説明を参照してくださいすることができ、ソースコードを見てEnableScheduling、我々は複数のプロジェクトを持っています。
* In all of the above scenarios, a default single-threaded task executor is used.
* When more control is desired, a {@code @Configuration} class may implement
* {@link SchedulingConfigurer}. This allows access to the underlying
* {@link ScheduledTaskRegistrar} instance. For example, the following example
* demonstrates how to customize the {@link Executor} used to execute scheduled
* tasks:
そのことについては、意図的にビットBaiduはまた、いくつかの書籍や記事を見て、私はSpringBootはタスクが同じデモしているタイミングについて説明しますが、......この方法は、シングルスレッドでは言及しなかった
私は、だからここにネットワーク上のコードを言いや書籍を参照することができますが、などの問題が表示されていないときに比較的詳細に理解無力があるはずです。
溶液は、例えば、SchedulingConfigurerインタフェースを達成することで、簡単です。
public class XXX implements SchedulingConfigurer{
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskExecutor());
}
@Bean(destroyMethod="shutdown")
public Executor taskExecutor() {
return Executors.newScheduledThreadPool(30);
}
}
第三ラウンド圧力試験結果は:TPS = 30
の改善された方法の第三ラウンド:
進行されている、されていない、少なくとも第1ラウンドの結果と比較して、我々は10倍に増加したが、この合理的か?私たちは、すべての挿入操作され、プラスの調査後にログインし、4500のレコードの挿入最終的な位置決めのバルクは、私たちがこのようなステートメントを挿入し、上記の10Sを必要としています。(MyBatisの3.1.1を使用して)
<insert id="insertBatch">
insert into xxx (msg_id, balance_type,
amount, account_id, user_id,
is_handle, create_time
) values
<foreach collection="list" item="item" index="index" separator=",">
(#{item.msgId,jdbcType=VARCHAR}, #{item.balanceType,jdbcType=VARCHAR},
#{item.amount,jdbcType=BIGINT}, #{item.accountId,jdbcType=BIGINT}, #{item.userId,jdbcType=VARCHAR},
#{item.isHandle,jdbcType=INTEGER}, #{item.createTime,jdbcType=TIMESTAMP}
)
</foreach>
</insert>
MyBatisのforeachの文法用いる場合には、長さ500K SQLのそれぞれは、ネットワークの遅延も実質的に除外され、試験された、XXX値(AA、BB)、(CC、DD)は、SQL文への挿入を生成することができない助けることが疑問に始まりますforeachの文法MyBatisのため、SQL上記のコードによって生成され、次いでMyBatisの、以下のサンプルコードを介して行います。
<insert id="insertBySql" parameterType="com.moext.SqlVo" >
${sql}
</insert>
圧力試験結果の第4ラウンド:TPS = 300、約100下の第二のバッチを開始する
第4ラウンド改善:後の負最初の重要なデータギャップとデータ量後続のバッチの場合、対象問題のMysql、一意のインデックスが存在する元のフィールドMSG_ID(値UUID)を位置決めする、唯一の指標としてUUIDを使用するには、2つの問題がある:
1は、長すぎる
、無秩序、各挿入操作2、インデックスの再構築は効率的ではない
、この分野では歴史的な理由によるものです、実際には、アクセスできません、それはそこに削除されています。
第五の車輪圧測定結果:TPS = 300 +
要約:
シリアルシリアル単一の操作に最初のバッチ処理からのプロセスのパフォーマンスの最適化は、クロスプロセス(DBへのサービス)対話型データの量を増加させるたびに、次にEnableSchedulingにおけるTPSの不安定性によりシングルスレッド問題SpringBootの存在を発見し;
最後に、過去の経験およびテストの比較に基づいてforeacheのMyBatisのを使用して、パフォーマンスの問題を見つけ、TPSは、突然最後の秋、最終的にスタンドアローンであろうシリアル処理TPSが300以上に増加した問題の唯一の指標としてUUIDを検索する方法。これまでのところ唯一のパフォーマンス。TPSを高め、さらに複数のマシンを使用するには?読者は、スケーラビリティの設計を検討します。フォローアップのプレゼンテーションを行うこと。