并发知识

  有高并发的开发需求,首先要规划你的硬件、软件架构,那规划的依据是量化的数据,如PV,QPS;还要清楚软件的特性和用什么技术,然后还要通过性能测试进行辅助,如JMeter , 根据测试工具压测,得出整体服务的响应时间,吞吐量,另外还要对数据进行分析,看是否存在数据错乱的情况。

  • 缓存

主要是避免数据库IO的瓶颈。一般在内存进行处理,当然单机缓存容量有一定局限,可以N台机器互联共享内存,则采用分布式缓存,在高并发情况下,使用缓存有一个思路是 相关业务操作及代码实现可以完全在缓存中操作,有些数据可以先预热到缓存中,服务运行的时候可以直接从缓存中读取,那缓存中数据更改后最终要同步到数据库,可以异步+队列的方式进行消息订阅和发送或者采用轮询定时从缓存中取出数据写入到数据库,在设计过程中格外注意同步失败或出现故障的情况,要有重试机制;其实在独立模块,独立服务中,有些服务并发并不高,那数据可以直接先写入到数据库中,而后再被缓存起来;最后 依据CAP定律,如果服务可用,并是容量分区这里是如果采用分布式缓存,最后只能是弱一致性,所以我们设计是解决90%以上的问题(当然如果能解决99.999%的问题更好了),另外10% 可以人工介入加以解决。

  • 限流

高并发情况下肯定不能将全部请求全部接受并一次性处理,那服务有被搞崩溃的可能。

那就可以将部分重复请求丢弃,可以使用Nginx 的 对客户端IP进行限制;

同时高并发下肯定有些重要数据资源会存在竞争,如何保持数据一致性,使用锁机制,

悲观锁,会严重影响性能,但不会存在脏读,写错的情况;

乐观锁,会存在脏读的情况,但能保证数据写入没有问题;

分布式锁,一般我们采用分布式锁,使用Redis 的SETNX 特性,Redis 是单线程,存在事务,但事务没有回滚机制,Redis的事务是命令集的方式,如 SETNX 如果不存在Key 值则返回true, 如果已存在Key 值则返回false  , 如果返回false 代表请求已存在,则请求被直接丢弃,其实Redis 的 SETNX 和 Membcached 的Add 有点类似,然后使用队列将请求串行化,到数据库基本访问不会太高,最后的数据库起码要最好主从模式,避免单一故障,最好数据冗余。

  • 算法

对请求进行限流有个很常用的手法:

令牌桶,我们先申请访问的token,并注入到一个桶容器中,设置容器的最大token 量,超过的请求直接丢弃,当请求访问时验证token 是否存在,如存在则正常处理后续业务逻辑并删除token,,否则直接丢弃请求,以上算法的实现方式可以使用 Redis 中的 SETNX +  Delete  命令实现;

  • 队列

成熟的队列消息中间件,其中RabbitMQ 是较为常用,支持消息的持久化,避免中心服务DOWN 机后消息丢失;支持ACK机制,当消费者宕机或其它网络原因导致没有收到消息,则队列会进行重发消息,直到消费者确认收到通过BasicAck 命令进行发送则消息从队列中删除;有限流机制,可以通过内存大小,磁盘大小及上游流量大小三种方式对请求进行限流;可以集群,但各服务器队列进程不互相通信,所以需要客户端实现分布式,算法可以采用哈希一致性;

 

posted @ 2019-08-14 20:35  peterYong  阅读(144)  评论(0编辑  收藏  举报