提升系统并发性能

应用系统的性能是关系到客户感官的重要因数,因此我们在设计系统时性能是必须要提前考虑的,必须在真正开发前做针对整个系统设计的系统测试,测试该设计方案是否满足客户的性能要求。

而在影响性能的众多因数中,因数据库设计不合理和应用系统中对数据操作设计不合理导致的性能瓶颈又由为突出。在一般情况下对数据层的优化没有在应用层优化所得到的性能提升高。下面举几个在实际系统中常常会遇到的几个场景以及提供的解决方案,请各位朋友斧正。

要在数据层优化,必须了解数据库的锁机制。锁分为共享锁和排它锁。如select一般需要的是共享锁,update,delete需要排它锁,而锁又分级别,如行锁,页锁,表锁等等。

  1. 对高频率update导致的性能瓶颈的优化:
    场景1:在服务中需要记录某项资源的浏览次数。最常见的同时也是最简单的做法是在用户事务时间中对该项资源的浏览记数执行update操作。导致的状况就是高频度的修改同一条记录。先说不修改任何代码的优化方案。当数据库再执行update操作时,因为要修改数据,因此必须获得排它锁,并且根据where语句过滤出的记录数量决定锁的级别,因此如果where语句后面是主键判断的话,那么数据库只需要在该行加一行锁即可,不会影响数据库对其他行的操作,否则如果过滤出多条数据,数据库可能会升级为页锁甚至表锁,那这样的话就可能会导致要修改其他行数据的连接处于锁等待状态,导致并发处理量降低。因此做update,delete数据时where语句越严格则性能越高。但是即使是这样设计,访问数据库的频率依然非常高,解决的办法为先在内存中将该资源的浏览记数执行加加操作,每隔一定时间将该值同步到数据。但是如果使用这样的方案假如系统中有大量业务资源的话缓存的记数可能会占用大量内存空间(如论坛类业务),并且如果kill掉进程的话,可能会损失一部分数据,因为有些数据在kill前还没有同步到数据库中(除非监测系统消息,在进程停止之前同步数据)。还有其他解决方案:往数据库插入事件对象。每浏览一个对象,向数据库中插入一个可以标志该事件的记录,待数据库空闲时根据这些事件消息统计浏览次数,将其同步到资源浏览记数中。但是这将造成对数据库的大量insert操作,下面会介绍对大量insert操作的设计优化方案。事件表还有一个特性是在数据层不应该设置主键以及任何索引,因为任何的索引(包括主键)都会造成insert操作性能大大降低。但是为了能够唯一性标志某一列以利于某些数据库操作(如删除某条记录),可以在应用层设计一个唯一性值的生成器(如UUID),唯一性由应用层维护而不是数据层,记录事件生成时间是非常必要的,其次是事件表的数据转移,这样不仅可以提升统计的速度还可以降低对表空间的压力(事件表数据量非常大,如果一直存储在同一个表空间,容易导致空间不足的危险,所以将其转移到另一个表空间不失为一个好办法,即使出现空间不足也是被转移到的表空间不足,不会导致)。
    场景2:对外键进行更新。如果在update操作中更新外键,数据库将检查外键约束是否成立,这也是一个非常浪费时间的操作。所以生成的update语句中避免不必要的对外键的更新操作。hibernate中就有这个问题(我当时使用的版本的确有该问题,它不区分哪些字段的确是做了修改,都会将所有字段添加到update操作的sql中),导致非常严重的性能问题。
     
  2. 对高频率insert导致的性能瓶颈的优化:
    1:其中一条是上面已经提过的:某些表在数据层不设置主键,如事件表,日志表。如果某些外键约束不是很严格,可以去掉外键约束。
    2:高频率的insert操作会造成索引并发等待以及磁盘的并发访问,如果能够将对同一个表的访问分散则可以变相地降低负荷。如在SMS业务中,接收用户发送的上行消息。可以将消息表分为10个表,如smsmessage1,msmmessage2...,当向数据库中插入上行消息时,可以随机选择一个表插入,到合适时间在将所有表中的数据合并。这样就将对一个表的负荷分配到多个表中,降低了对同一个表的操作频率。同时每个表可以存放在不同的磁盘上,对磁盘的访问频率也得以降低。(如果有主键的话需要考虑合并数据时各个表中的主键可能重复的问题)
     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值