精华内容
下载资源
问答
  • 一般来讲,连接MySQL服务器的应用都会和MySQL服务器分开,这样的好处显而易见,缺点也很明显,尽管CPU,内存和磁盘IO资源不会和其它应用程序发生争用了,但对网络带宽和稳定性的依赖增强了。权衡利弊,分开部署是...

    从客户端连接MySQL服务器开始,一步一步来优化的MySQL服务器的设置。

    一般来讲,连接MySQL服务器的应用都会和MySQL服务器分开,这样的好处显而易见,缺点也很明显,尽管CPU,内存和磁盘IO资源不会和其它应用程序发生争用了,但对网络带宽和稳定性的依赖增强了。权衡利弊,分开部署是大多数公司的选择。

     

    那么接下来,我们就在应用和MySQL服务器分开部署的场景开始我们的工作。

    1.客户端连接MySQL服务器

    客户端通过网络连接MySQL服务器,协议是TCP协议,那么很容易的,我们就会想到需要调整下系统的网络连接数设置,打开文件数限制,还有和TCP连接相关的一些其它比较重要的内核参数,来适当提高系统能够承载的网络连接数和网络连接质量。这里需要使用到sysctl命令和sysctl.conf相关的配置。有实际需要的同学,熟悉下相关内容,深入了解一下其中各个重要参数的意义和调整方法。系统调整好了,那么接下来客户端的网络连接请求就来到了MySQL服务器的监听端口,MySQL服务器会调用accept()接受这个连接请求,如果大家熟悉socket编程的话,会了解到中间有一个调用listen()函数的过程,这个listen()函数是能够传入两个参数的,一个是socket套件字,一个是可排列的最大的请求队列数,对应MySQL的参数设置就是back_log,如果请求连接很多,就像买东西需要排队的道理一样,这个时候,连接请求会被安排到请求队列中排队,但这个请求队列也不是无限大的,和back_log这个参数的设置值有关,如果队列中已经排满了,新的连接请求会被丢弃掉,出现无法连接到MySQL服务器的情况,一般情况下,客户端的连接请求会被accept立即响应,新创建一个和请求客户端的TCP连接,这个时候MySQL的连接数就多了一个。这个时候MySQL的另一个参数max_connections的剩余可用连接数就会少一个。由于MySQL是多线程的,实际情况是MySQL服务器会创建一个新的线程和客户端进行数据通讯。既然用到了线程,MySQL服务器中另一类和线程相关的参数thread_cache_size,thread_pool_size等一些和提升连接响应请求速度的参数就派上用场了。至此,客户端连接到服务器的过程似乎就完成了,这里我省略了几个参数的介绍,比如:max_connect_errors,character_set_connection,collation_connection,skip_name_resolve,skip_networking,skip_external_locking等几个比较常用的参数,根据需要来进行设置,设置前搞清楚这些参数的意义和实际的需求。不要南辕北辙就好。

    2.客户端发起查询数据的请求

    客户端发起select查询请求,查询需要的数据,是MySQL服务器提供的常规服务,一个查询请求会被MySQL服务器怎样处理,又受到哪些参数的影响呢,下面就带着这个问题,来看下一步如何进行优化调整,一个select查询语句,来到MySQL服务器,会首先被查询计划优化分析器分析怎么查数据效率最高,举个例子:

    select id, name, age from person where name='turbo';

    查询计划优化分析器会分析这个语句,先找到from关键字,找到对应的数据集,分析这个数据集包含那些索引,然后分析where子句,确定一下是否有可用的且合适的索引,如果索引不合适或者使用索引的效率不理想(是否理想是查询优化分析器根据算法估算的,不是十分精准),查询计划优化分析器就不会使用这个不太合适的索引,如果没有可用索引,会进行全表扫描,找到满足条件的所有记录。

    读取数据时,会从innodb_buffer_pool中查找数据,MySQL参数innodb_buffer_pool_size是用来设置innodb_buffer_pool的大小的,如果未找到,会发出页缺失异常,此时会发生磁盘到内存的数据读取,补全缺失的数据页,MySQL的状态变量Innodb_buffer_pool_reads保存的就是发生这种情况的次数,和MySQL的状态变量Innodb_buffer_pool_read_requests相比,如果占比过大,比如超过5%,理想情况不超过1%,就需要调整innodb_buffer_pool_size的大小了。

    所有数据记录会以类似链表的形式读取到内存中,这个innodb_buffer_pool设置多大才合适呢,我的经验是如果是专用MySQL服务器,直接设置为物理内存的75%,如果服务器内存很大,比如是128G的,也可以设置成110G,前提是要给系统运行时需要的进程留下足够的内存空间,也给MySQL服务器运行时需要的其它缓存留下足够可用的内存空间。如果不是专用的MySQL服务器,检查一下Innodb_buffer_pool_pages_total和Innodb_buffer_pool_pages_data的值,如果这两个值很接近,就需要扩大innodb_buffer_pool了,保证有至少5%的Innodb_buffer_pool_pages_free空间,另外,也可以关注一下Innodb_buffer_pool_wait_free的值,如果这个变量不为0,也说明innodb_buffer_pool可能太小了。

    这里要留意的是,在发生Innodb_buffer_pool_reads的时候,如果磁盘响应过慢,就会影响MySQL服务器的处理速度,所以配备更快速的磁盘或者SSD能够降低磁盘响应过慢的影响,但无论怎样提升磁盘的速度,都无法从根本上提高全表扫描的效率。针对全表扫描最有效的办法是设置合理的索引。配备更快的磁盘,缩短的只是读磁盘数据的时间,补缺页的速度更快了,全表扫描的时间还是那么多。

    另外还要注意多核CPU的numa问题,在运行数据库的服务器上,使用numa的调度算法是不合适的,会引起频繁的上下文切换,还有可能直接触发操作系统的swap动作,需要关闭numa的调度方式。

     

    这里暂时不对查询加锁做更多的说明,唯一要说明的是,如果一个很慢的查询还在运行(持有元数据锁),此时做更改该表结构的操作,会引起阻塞(给表添加排它锁),接下来对该表的查询请求都无法完成,这个要避免。

     

    关于磁盘吞吐量的设置还有一些参数,会在刷脏页部分进行说明。

    3.客户端发起insert请求

    MySQL支持ACID的引擎是innodb,是目前MySQL服务器使用最广泛的引擎。

    在一次针对多个表的insert操作时,MySQL服务器为保证数据写入的ACID,使用了undo_log和redo_log。当请求到达,MySQL为该请求分配事务ID,开启事务,查找定位数据,记录insert的undo记录,记录undo的redo log 入redo buffer,进行insert 元组插入,及实际的插入操作,将数据写入innodb_buffer_pool,记录插入的redo log 入redo buffer,事务结束。

    4.客户端发起update请求

    当请求到达,MySQL为该请求分配事务ID,开启事务,查找定位数据,记录update的undo记录,记录undo的redo log 入redo buffer,进行update操作,会先将数据写入缓存innodb_buffer_pool,记录update的redo log 入redo buffer,事务结束。

    5.客户端发起delete请求

    当请求到达,MySQL为该请求分配事务ID,开启事务,查找定位数据,记录delete的undo记录,记录undo的redo log 入redo buffer,进行delete操作,会先将数据写入缓存innodb_buffer_pool,记录delete的redo log 入redo buffer,事务结束。

     

    以上3种操作都涉及了对undo日志的操作,undo日志是innodb实现mvcc的重要手段,理解innodb的事务实现过程对于理解数据库的操作还是很有必要的,这中间涉及到了大量MySQL的核心参数的调整和优化:

    首先,这里提到了对innodb_buffer_pool的写操作,更改的内容如何同步到磁盘,pool中更改了多少内容呢,还有多少没有同步到磁盘,谁负责把pool中的脏数据同步到磁盘。 这个问题就是针对innodb_buffer_pool的刷脏操作,一个一个来回答上面提到的问题:

    1. MySQL服务器中有一个checkpoint机制,默认每隔一定的时间或达到一定的值(innodb_max_dirty_pages_pct,innodb_max_dirty_pages_pct_lwm,innodb_max_changed_pages,innodb_change_buffer_max_size)就会触发checkpoint,checkpoint会把innodb_buffer_pool中的脏页同步到磁盘。
    2. 那么我如何知道pool中有多少脏页呢,MySQL的状态变量Innodb_buffer_pool_pages_dirty,Innodb_buffer_pool_bytes_dirty分别使用不同的单位显示当前pool中有多少内容是需要同步到磁盘。
    3. 刷脏页是把内存的数据写入到磁盘,这里又涉及到了和磁盘的数据通讯,我们知道磁盘相比内存的访问处理速率是非常慢的,为了提高这个刷脏的速度,MySQL服务器有以下几个参数可以调整:(innodb_parallel_read_threads,innodb_read_io_threads,innodb_write_io_threads,innodb_page_cleaners,innodb_io_capacity,innodb_io_capacity_max,innodb_flush_method)
    4. 还有对undo_log的write和purge操作,可提供的设置参数innodb_log_buffer_size,innodb_log_files_in_group,innodb_purge_threads,这些都是MySQL中比较核心也比较影响性能的。

     

    提到了MySQL的写操作,还有一个doublewrite机制也是不得不说的,这个机制是干什么的呢,我们知道系统的内存页大小为4K,而MySQL的内存页默认为16K,如果在操作一个16K的页面时,写某一个4K的页面时系统崩溃了,MySQL是无法通过之前提到的那些日志恢复的,因为日志对应的页是损坏的,意味着不可恢复的故障。doublewrite机制是为了避免出现这个问题而设计的,doublewrite会以顺序写的方式写入到一个1M的磁盘空间,用来确保内存中的页损坏之后可以得到恢复。如果可以接受页损坏造成的损失,关闭doublewrite能提高MySQL的性能。

     

    关于crash丢失数据的控制参数还有两个不妨也说一下好了,它们就是常说的双1参数,双1的设置可以确保最少的数据丢失。但也带来了巨大的性能损耗,这个双1设置就是指的innodb_flush_log_at_trx_commit(这个设置为1可以确保undo_log buffer中的内容会及时写入到磁盘)和sync_binlog(这个是针对二进制日志的,设置为1可以确保从库不会丢失日志)。这个双1设置几乎牺牲了所有为性能提升设计buffer所带来的增益。是否使用双1设置,见仁见智。

     

    这里再补充几个参数,作为结束:innodb_buffer_pool_instances,table_open_cache,table_open_cache_instances

    一个是用来设置开几个pool的,一个是用来设置开几个打开表缓冲区的。为了整个系统的性能和承载力,使用更快的磁盘无疑是正确的选择,虽然MySQL时时刻刻都在想办法避免使用磁盘,即便使用也总是尽量平滑一些,但终归是要访问它的。

     

    可以看到,这些设置都在努力实现同一个目标,就是尽力避免直接访问磁盘。因为整个计算机系统中,最慢恐怕就是磁盘设备了。如果避免了磁盘瓶颈,可以极大的提升整个系统的承载能力。

     

     

    参考文档:

    一个简单insert语句的大概流程:https://www.jianshu.com/p/5248ca67eac2

    double write 浅析:https://blog.csdn.net/a545578125/article/details/46272663

    MySQL Memory Calculator:http://www.mysqlcalculator.com/

     

    最近对Linux的swap机制很感兴趣,一直挖掘这方面的知识点。对swap也有了新的认识。

    Swap触发机制分两种,一种是系统正常检查内存时,将内存中长久访问不到的数据交换到了swap空间,另一种情况是应用程序申请内存的时候,发现物理内存不够用了,触发系统的swap机制,这个时候,系统的表现就会出现卡顿,影响系统性能了。

    因此,系统发生swap并不是说明现在出现了性能问题,不用着急出现swap的问题,只要排除了第二种情况,系统其实是没有问题的。

    和swap相关的几个内核参数:vm.min_free_kbytes,zone_reclaim_mode,vm.swappiness

     

    查看swap有哪些进程在使用,使用了多少空间,可以执行下面的命令:

    for i in `cd /proc;ls |grep "^[0-9]"|awk ' $0 >100'` ;do awk '/Swap:/{a=a+$2}END{print '"$i"',a/1024"M"}' /proc/$i/smaps ;done |sort -k2nr

    另一种方法:

    #!/bin/bash
    
    # Get current swap usage for all running processes
    
    
    function getswap {
    
    SUM=0
    
    OVERALL=0
    
    
    for DIR in `find /proc/ -maxdepth 1 -type d | egrep "^/proc/[0-9]"`
    
    do
    
        PID=`echo $DIR | cut -d / -f 3`
    
        PROGNAME=`ps -p $PID -o comm --no-headers`
    
        for SWAP in `grep Swap $DIR/smaps 2>/dev/null| awk '{ print $2 }'`
    
        do
    
            let SUM=$SUM+$SWAP
    
        done
    
        echo "PID=$PID - Swap used: $SUM - ($PROGNAME)"
    
        let OVERALL=$OVERALL+$SUM
    
        SUM=0
    
    done
    
    echo "Overall swap used: $OVERALL"
    
    } 

     

    getswap

     

    参考文档:

    Linux SWAP 深度解读:https://blog.csdn.net/wh8_2011/article/details/51798407

    Linux之swap知识整理:https://www.cnblogs.com/madsnotes/articles/5907952.html

    展开全文
  • 线程池——3大方法、7大参数、4种拒绝策略 池化技术 程序运行,本质:占用系统资源!...线程池工作流程 当一个任务通过submit或者execute方法提交到线程池时候,如果当前池中线程数(包括闲置线程)小于

    目录

    池化技术

    线程池工作流程

    线程池:3大方法

    线程池:7大参数

    4种拒绝策略

    拓展:CPU密集型和IO密集型(涉及 调优)


    【线程池】学习脉络——3大方法、7大参数、4种拒绝策略

    池化技术

    程序的运行,本质:占用系统资源!优化资源使用——池化技术

    例:线程池、JDBC连接池、对象池......

    池化技术:事先准备好一些资源(默认大小,最大值),有人用,就来拿,用完归还。

    线程池好处:

    • 减低资源消耗(重复利用已创建的线程)
    • 提高响应速度(创建和销毁十分消耗资源)
    • 方便管理线程

    线程复用、可控制最大并发数、管理线程

    线程池工作流程

    • 当一个任务通过submit或者execute方法提交到线程池的时候,如果当前池中线程数(包括闲置线程)小于coolPoolSize,则创建一个线程执行该任务。
    • 如果当前线程池中线程数已经达到coolPoolSize,则将任务放入等待队列
    • 如果任务不能入队,说明等待队列已满,若当前池中线程数小于maximumPoolSize,则创建一个临时线程(非核心线程)执行该任务。
    • 如果当前池中线程数已经等于maximumPoolSize(此时任务队列已满),此时无法执行该任务,执行拒绝策略

    注意:

    1)当池中线程数大于coolPoolSize,超过keepAliveTime时间的闲置线程会被回收掉。回收的是非核心线程,核心线程一般是不会回收的。如果设置allowCoreThreadTimeOut(true),则核心线程在闲置keepAliveTime时间后也会被回收。

    任务队列是一个阻塞队列,线程执行完任务后会去队列取任务来执行,如果队列为空,线程就会阻塞,直到取到任务

    2)任务来时的处理顺序:

    • 创建新线程
    • 放入任务队列等待(corePoolSize已满)
    • 队列满,创建新线程(此线程处理完任务后闲置keepAliveTime时间会被回收)
    • 继续加任务,拒绝策略(maxmumPoolSize已满)

    线程池:3大方法

    Executor框架的核心类是ThreadPoolExecutor——线程池的实现类。

    通过Executor框架的工具类Executors,可以创建3种类型的ThreadPoolExecutor:

    • FixedThreadPool
    • SingleThreadExecutor
    • CachedThreadPool
    public class Demo01 {
        public static  void main(String[] args){
    //        ExecutorService threadPool = Executors.newSingleThreadExecutor();  //单个线程
    //        ExecutorService threadPool = Executors.newFixedThreadPool(5);  //创建一个固定大小的线程池
            ExecutorService threadPool = Executors.newCachedThreadPool();  //可伸缩的线程池
    
    
            try {
                for(int i=0;i<10;i++){
                    threadPool.execute(()->{
                        System.out.println(Thread.currentThread().getName()+" ok");
                    });
                }
    
            }catch (Exception ex){
    
            }finally {
                threadPool.shutdown();
            }
        }
    }

    线程池:7大参数

    源码分析--

    public static ExecutorService newSingleThreadExecutor() {
            return new FinalizableDelegatedExecutorService
                (new ThreadPoolExecutor(1, 1,
                                        0L, TimeUnit.MILLISECONDS,
                                        new LinkedBlockingQueue<Runnable>()));
        }
     public static ExecutorService newFixedThreadPool(int nThreads) {
            return new ThreadPoolExecutor(nThreads, nThreads,
                                          0L, TimeUnit.MILLISECONDS,
                                          new LinkedBlockingQueue<Runnable>());
        }
    public static ExecutorService newCachedThreadPool() {
            return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                          60L, TimeUnit.SECONDS,
                                          new SynchronousQueue<Runnable>());
        }

    ——开启线程,本质:ThreadPoolExecutor

    public ThreadPoolExecutor(int corePoolSize,         //核心线程池大小
                                  int maximumPoolSize,     //最大线程池大小
                                  long keepAliveTime,         //超时 无人调用,则释放
                                  TimeUnit unit,         //超时单位
                                  BlockingQueue<Runnable> workQueue,         //阻塞队列
                                  ThreadFactory threadFactory,     //线程工厂,创建线程,一般不用动
                                  RejectedExecutionHandler handler) {     //拒绝策略
            if (corePoolSize < 0 ||
                maximumPoolSize <= 0 ||
                maximumPoolSize < corePoolSize ||
                keepAliveTime < 0)
                throw new IllegalArgumentException();
            if (workQueue == null || threadFactory == null || handler == null)
                throw new NullPointerException();
            this.acc = System.getSecurityManager() == null ?
                    null :
                    AccessController.getContext();
            this.corePoolSize = corePoolSize;
            this.maximumPoolSize = maximumPoolSize;
            this.workQueue = workQueue;
            this.keepAliveTime = unit.toNanos(keepAliveTime);
            this.threadFactory = threadFactory;
            this.handler = handler;
        }

    手动创建一个线程池:

    public class Demo02 {
        public static  void main(String[] args){
            //自定义线程池! ThreadPoolExecutor
            ExecutorService threadPool = new ThreadPoolExecutor(
                    2,
                    5,
                    3,
                    TimeUnit.SECONDS,
                    new LinkedBlockingDeque<>(3),
                    Executors.defaultThreadFactory(),
                    new ThreadPoolExecutor.AbortPolicy()
                    );
    
            try {
                //线程池最大承载任务数目 = max + Queue 即5+3=8个任务。
                //若for循环9次,则触发拒绝策略
                for(int i=0;i<10;i++){
                    threadPool.execute(()->{
                        System.out.println(Thread.currentThread().getName()+" ok");
                    });
                }
    
            }catch (Exception ex){
                ex.printStackTrace();
            }finally {
                threadPool.shutdown();
            }
        }
    }

    说明:线程池最大承载任务数目 = max + Queue 即5+3=8个任务,若for循环9次,则触发拒绝策略

     

    4种拒绝策略

    线程池等待队列都满时,线程池处于饱和状态,再提交新任务会触发拒绝策略。

    (1)AbortPolicy (默认)

    直接抛出异常——类型为RejectedExecutionException的RunningException,(优点)可以感知被拒绝,以便决定是重试还是放弃提交任务。

    (2)DiscardPolicy

    新任务直接被丢弃,不会通知。(缺点)提交任务时根本不知道这个任务被丢弃,造成数据丢失。

    (3)DiacardOldestPolicy

    丢弃存活时间最长的任务,可以腾空间给新提交的任务。

    (4)CallerRunPolicy

    新任务交给提交任务的线程执行,谁提交,谁执行。

    优点:

    • 新提交的任务不会被丢弃,不会造成数据丢失
    • 提交任务的线程执行任务,而执行任务比较耗时——这段时间,提交的任务被占用便不会提交新任务,减缓提交任务速度(=负反馈);再此时间内,线程池内线程执行调一部分任务,腾出空间,给线程池留出缓冲期

     

    拓展:CPU密集型和IO密集型(涉及 调优)

    问:最大线程数maxmumPoolSize如何确定?

    答:

    (1)任务是CPU密集型:maxmumPoolSize = CPU核数。   保持CPU效率最高!(并发 VS 并行)

    Runtime.getRuntime().availableProcessors();//获取CPU核数

    (2)任务是IO密集型:maxmumPoolSize = 2 *  判断程序中耗IO的线程  (程序中IO十分占用资源)

     

     

    展开全文
  • 20世纪初,看板首先激起了商业领袖的兴趣,当时看板主要用于优化软件开发的工作流程。如今,看板应用于知识工作的所有学科,帮助团队可视化、管理和优化工作。 科学也表明了看板的好处:大脑处理视觉信息的速度比...

    对外行而言,看板听起来可能更像是在寿司店要点的开胃菜,而不是项目管理方法。看板可能无法食用,但它是日本的出口产品。20世纪40年代,丰田汽车(Toyota)的一名日本工程师创建了看板,用于组织工作和解决公司制造系统的效率低下问题。

    20世纪初,看板首先激起了商业领袖的兴趣,当时看板主要用于优化软件开发的工作流程。如今,看板应用于知识工作的所有学科,帮助团队可视化、管理和优化工作。

    在这里插入图片描述

    科学也表明了看板的好处:大脑处理视觉信息的速度比处理单词快6万倍。通过利用视觉信息的内在力量,看板可以促进交流和理解。

    看板可通过以下不同方面使团队的项目管理受益:

    多功能性

    看板背后的中心思想是通过视觉信号进行交流,视觉信号的好处涉及行业和职称。由于看板具有普遍适用性,因此公司中的每个团队都可以实施看板,从工程到市场营销再到管理。它的多功能性使团队成员和项目可以轻松地、跨职能地无缝移动,例如将内容项目从编辑移动到图形设计,或者新软件功能从集成移动到测试。

    持续改进

    看板的指导原则之一是每个人都应专注于持续改进。看板的项目管理可视系统使审核流程和改进变得更加容易,从而减少了浪费,简化了工作流程并减少了开销。

    响应能力

    在看板开始的汽车行业,看板的创建是为了更好地匹配库存和需求,只有在库存很低时才启动流程,这种做法被称为“及时交付”。在项目管理应用程序中,响应能力仍然是看板的核心优势之一。使用看板可以更灵活地响应业务需求。

    产量增加

    看板鼓励团队在任何时候限制他们正在进行的工作,这个概念被称为限制“在制品”(WIP)。限制在制品(WIP)鼓励团队合作完成工作,尽可能避免分散注意力处理多项任务。这种增强的协作和高度集中的注意力让使用看板的团队更快地完成更多的工作。

    赋权团队

    整个团队拥有看板系统,共同承担完成工作的职责。看板使团队能够做出更敏捷的决策,从而以创新和高效的方式推进项目。

    产品更完美

    看板专注于持续改进和对问题的敏捷响应,这通常意味着从头到尾完成的项目错误更少,返工也更少。看板把质量控制放回项目管理流程中,收获更准确的结果。

    使用专业的看板工具有助于企业改进项目流程,比如8Manage 看板项目管理软件,充当实时的项目信息存储库,在系统内重点突出瓶颈问题以及可能妨碍工作实践顺利开展的其他问题,帮助企业实现活动和责任可视化、促进项目日程安排和进展管理。

    在这里插入图片描述

    8Manage 看板支持以下四个看板原则:

    1. 从你现在着手的事开始

    看板的灵活性允许看板对现有的工作流、系统和流程进行覆盖,而不打乱已经成功完成的事项。看板将自然而然地突出需要解决的事项,有助于评估和计划变更,使实施尽可能不具有破坏性。

    2.同意追求渐进式变革

    看板方法论的设计目的在于满足最小阻力,因此鼓励对当前流程进行持续的、小的渐变式变革和渐进式变革。一般而言,不鼓励彻底变革,因为受到恐惧和不确定性的影响,这些变革通常会遇到阻力。

    3.尊重当前的流程、角色和职责

    看板承认现有的流程、角色、职责和头衔具有价值,它们通常值得保留。看板方法不阻止变革,但也没有把看板当作“万能的灵丹妙药”。看板的设计目的在于促进和鼓励渐进的、合乎逻辑的变革,同时不引发对变革本身的恐惧。

    4.鼓励各级领导行动

    这是最新的看板原则。这个原则提醒我们,某些最好的领导能力来自团队一线员工的日常行为。为了在团队/部门/公司层面上达到最佳绩效,每个人都要培养持续改进的思维模式,这一点很重要。这不可能是管理级别的活动。

    在正确构建、管理和运行的基础上,8Manage 看板充当实时的项目信息存储库,并在系统内重点突出瓶颈问题以及可能妨碍工作实践顺利开展的其他问题。8Manage看板项目管理软件具备的丰富管理功能,不仅能为企业带来最有效的决策支持和管理,生成高价值的完整数据,还能提供可用于机器学习的数据,最大化提升企业项目管理效益。

    展开全文
  • 一次批量操作的优化

    2017-03-18 15:47:00
     假设我这边系统是R(received),对方系统是S(send),那么现在的工作流程是这样:  在线上数据量比较大情况下(单日平时交易量10W量级,还款日接近百万),这种单笔请求单笔处理方式虽然有一定好处,却...

      最近在做账务系统的批量核销接口的优化,该接口的功能抽象来说就是暴露给另一个系统,每次调用会进行计算并更新库里的值(感觉好普通的样子)。

      假设我这边的系统是R(received),对方系统是S(send),那么现在的工作流程是这样的:

      在线上数据量比较大的情况下(单日平时交易量10W量级,还款日接近百万),这种单笔请求单笔处理的方式虽然有一定好处,却会导致性能问题。在现有业务流程已经确定不会有太大更改的情况下,对这一情况进行了分析和优化:

      1.请求分充值请求和消费请求。充值请求是商户维度的,而消费是订单维度的。而商户则与订单是一对多的对应关系,产品与商户的关系也是一对多。除开特定的某一产品,每一商户下均有几千到几十万不等的订单数目。

      2.在日记账(可看做交易信息表)中存储了发生交易的订单号以及商户号。核销也是通过这个表的数据进行的。

      3.商户之上还有产品的维度,产品与商户的对应关系基本是一对一,有一个特例存在一个产品对应几百的商户的情况。

      4.优化方向可以从商户和产品的角度入手,考虑到底是从商户的维度进行核销请求还是产品的维度。考虑到每日交易的结算单是从商户维度产生的,因此确定以商户的维度进行核销请求,一方面保证了对外接口的维度统一,一方面由于只有一个产品是特殊情况,因此不打算因为它而影响整个设计。

      综合以上考虑,优化之后的流程图如下图:

      这样可以省去大批量核销过程中产生的网络通讯耗时,但是实际测试过程中发现性能表现并不理想,后来用 yourKit 检测了下运行时耗时,发现是因为异步处理新启动了线程,导致事务失效,而产生了三次数据库操作导致的,于是想到能否将整个商户的核销作为一个事务提交,这样相对于单笔核销而言省去了若干次数据库操作,应该性能上犹有过之。具体spring手动控制事务可以参见这里:。

      然而这样做完之后发现性能获得了大幅度提升,之前单笔操作的耗时大概是150~500ms 之间,手动控制事务后单笔耗时只有30~50ms。然而在并发操作中发现了另外一个问题:如果在核销商户 A 的过程中(假设处理线程的名称为 Thread-A),商户 B 同时进行核销操作(假设处理的线程名称为 Thread-B),如果 A 商户核销数目较大,达到几万甚至几十万的级别,那么 Thread-B 会因为长时间拿不到数据库中表的权限而抛出 deadlock 异常,这明显与我们想要的结果不符,因此只能继续想对策。

      之后想到每指定笔数(比如每100笔)进行一次事务提交,这样在兼顾性能的同时还可以保证并发操作不会出现异常。这样导致的另外一个问题是,如果商户 A 中有1000条数据,在核销第500~600笔中的某一笔失败了的话,这个区间的操作会回滚,但是之前的数据并不会,这样一笔请求回调失败了很难发现错误点,也不好进行重推操作。为了解决这个问题,想了两个方案:

      1.在日志中每次开启一次事务就在日志中打印该批操作的商户号和起止编号,同时在提交的时候和出现异常的情况下也打印出来并报警。这样如果发现某一批次失败了的话,可以在日志中查询并重新推送这笔请求,然后在代码中加以控制,只处理指定区间的核销。

      2.在日记账表中添加标志位,表示该笔是否成功核销,处理的时候将每笔处理过的标识为成功,并且只处理标志位不是成功的。这样在出现失败时重推请求,就不用考虑其他事情。

      在仔细分析对比之后把第一种方案筛掉了,原因是依赖日志不如依赖数据库稳定,二来第二种方案逻辑上更容易理解。

      以上。

    转载于:https://www.cnblogs.com/kangyun/p/6574455.html

    展开全文
  • 采购看板是一种可视化工作管理方法和工具,旨在简化工作流程,尤其是采购团队的工作流程。例如,现代电子采购系统(比如8Manage SRM)具有采购看板模板,遵循寻源到付款(S2P)和采购到付款(P2P)流程,包括申请...
  • RPA(Robotic Process Automation),中文译为机器人流程自动化,也有人称之为数字化劳动力(Digital Labor),是一种智能化软件技术,它可以像人类一样,通过简单编程来完成设定好任务流程优化整个企业基础...
  • RPA(Robotic Process Automation),中文译为机器人流程自动化,也有人称之为数字化劳动力(Digital Labor),是一种智能化软件技术,它可以像人类一样,通过简单编程来完成设定好任务流程优化整个企业基础...
  • webpack2 终极优化

    2021-01-01 19:13:14
    这样做的好处是只要你不升级他们的版本这个文件永远不会被刷新。如果你把这些基础库和业务代码打包在一个文件里每次改动业务代码都会导致浏览器重复下载这些包含基础库的代码。以上的配置为: <pre><code>js /...
  • 工作流专题索引

    2009-07-10 10:15:00
    工作流管理系统的应用,使得办公自动化系统实现了综合化、集成化,帮助企业有效地改进和优化业务流程,提高业务工作效率、实现更好的业务过程控制,提高顾客服务质量、提高业务流程的柔性等。  工作流研究 ...
  • 以至于服务器在等待动态资源压缩的时间会抵消掉高压缩率带来的好处,但它非常适合静态文件压缩,因为它的解压速度很快。 使用Zopfli压缩可以比Zlib的最大压缩提升3%至8%。 <h3>3.2 图片...
  • §7.3 Oracle系统安装后的优化基础工作 94 §7.3.1 Oracle系统有关目录所有文件保护 94 §7.3.2 避免新用户使用默认system系统表空间 94 §7.4 Oracle系统所在服务器独立性 94 第9章 项目分析、设计与管理 94 §...
  • 用于 ARM:registered: Cortex:registered:-M 处理器的 DSP System Toolbox:trade_mark: 支持包,与嵌入式搭配使用时Coder:registered: 使您能够从 MATLAB:registered: System ... 作为 MATLAB 到 C 工作流程的示例,
  • 工作流技术一些优点

    2013-07-23 23:25:00
    企业实施工作流管理所带来的好处是非常明显的,这包括提高企业运营效率、改善企业资源利用、提高企业运作的灵活性和适应性、提高工作效率、集中精力处理核心业务、跟踪业务处理过程、量化考核业务处理的效率、减少...
  • 流程优化,改变?获得什么好处 2. 测试质量:没有重大漏测,获得项目组一致好评 3.工具引入和使用,获得业绩,抓包:fidler静态代码扫描,scan 4.测试用例设计方法: 三剑客: 1.功能测试框架 2.bug预防体系...
  • [提示]方案自我感觉不错,但本资源仅为方案介绍,有人怪分数多不是我有意,为系统自动设置. ...优化操作流程,减少操作步骤,并做到无培训即可使用 可以接入移动端访问数据 或者集成条码系统开发 增强企业IT一体化建设
  • AutoML是一个很宽泛的术语,理论上来说,它囊括从数据探索到模型构建这一完整的数据科学循环周期。...1.AutoML可为模型选择和优化提供切实的好处。2.它非常容易入手。很多AutoML框架都与scikit-learn或其他广
  • 易于优化的数据库查询以构建大小相等块(跳过+限制查询在处理大数据时非常慢)。 进步。 当您使用组/链/地图方案时,可以很容易地通过顶级父级监视总进度。 长时间独立任务还可以通知用户进度变化。 工人池。...
  • 眼下,RPA(机器人流程自动化)日渐成为业务流程优化重要解决方案和企业关注重点。 RPA不仅可以改善企业的工作方式,带来效率提升和超高投资回报率(ROI),其潜在其他好处也是其他工具所无法比拟,如改善...
  • 企业上马BPM项目真正目的是什么

    千次阅读 2017-11-07 09:02:30
    我们总是认为企业上马BPM项目,实施BPM优化,BPM电子信息化,这些工作的目的为了成本节约,流程管理顺畅了,自然节约了企业运行成本。但成本只是BPM带给企业众多好处一部分,而且也不是评估BPM成功最重要...
  • 这个架构基于squid、nginx和lvs等技术,从架构上对bbs进行全面优化和保护,...这个架构的特点和一些流程的说明:1、主域名和图片域名分离域 名分离可以使流量分离,缓存策略分离等等,好处诸多。bbs初期一定要做好规划
  • 线程池简述

    2021-04-08 14:22:00
    线程池 合理使用线程池的好处 java的线程是运用场景最多的并发框架,几乎所有需要异步或者并发执行任务的程序都可以使用线程池 ...线程池的工作流程 一个新的任务到达线程池时,线程池的处理流程如下:

空空如也

空空如也

1 2 3 4 5 6
收藏数 105
精华内容 42
关键字:

优化工作流程的好处