专栏名称: java一日一条
主要是讲解编程语言java,并且每天都推送一条关于java编程语言的信息
目录
相关文章推荐
芋道源码  ·  Guava黑魔法:在日志脱敏场景下的奇遇 ·  6 小时前  
芋道源码  ·  Spring Boot + ... ·  6 小时前  
芋道源码  ·  Spring Cloud Gateway ... ·  21 小时前  
芋道源码  ·  Spring Boot + URule ... ·  21 小时前  
芋道源码  ·  Spring-Security ... ·  昨天  
51好读  ›  专栏  ›  java一日一条

高并发系统的设计及秒杀实践

java一日一条  · 公众号  · Java  · 2018-09-29 13:19

正文

请到「今天看啥」查看全文


处理信息量要少

我们写业务代码的时候都有对应的业务对象,它们都存在一定的业务范围之内,比如类目、地区、日期等自身相关的维度。 一个系统中的业务对象,在多个维度的细分下,对应的量并不多,但如果一次全部都展示在一个页面/接口下,即使覆盖上了缓存,也会由于缓存占用空间过大或者缓存key数目过多、网络传输耗时、对象序列化反序列耗时等拖慢接口/页面响应速度。一般只要看一下这个页面/接口给出的业务对象的数量级,就能大致知道这个接口的性能了。

大家在做设计的时候,一般会估算一个接口的量级,如果一看就有几千几万个业务对象,就不会这样设计了,但是需要警惕的是业务对象数量级可变的情况,比如随着业务发展数量会快速增长,或者某些特殊维度下业务对象特别多。设计的时候要按照预估的最大量级来,并且对接口/页面做出数量的限制,如果发现当前返回的业务对象过多,可以继续根据业务维度来拆分,分次分批来处理。

举一个例子,比如一个影院下所有的活动场次,开始的时候一家影院下的场次有限,几十一百场,很好展示,后来随着业务发展,一个影院下各个影院下场次数到了几百一千,一次全部拿完,在高并发时,memcached缓存的multi get会出现很多超时,请求会打到mysql数据库,给系统很大压力。之后我们做了改造项目,每次根据用户的交互按照影片、日期、影院的维度来分批取,一次只有十几个场次,接口响应变快了,服务的压力也小的多。

做得巧

根据业务特性选择实现方式

平时涉及到的业务,总有属于它的特性,比如实时性要求多高,数据一致性要求多高,涉及什么维度的数据,量有多大等等,我们要根据这些特性来选择实现的方案,比如一些统计数据,如某类目下所有商品的最低价,按照逻辑需要遍历商品来获取,但这样每次实时读取所有的对象,涉及读取缓存数据库操作,接口会很耗时,但如果选择作业离线计算,把计算结果写表,加上缓存,搜索直接读取,显然会快很多了。

涉及到业务各阶段特性的例子就是秒杀系统,在第二部分秒杀实践中我会详细介绍。

合适选择和调用缓存

除了业务特性方面,缓存是业务对抗高并发非常重要的一个环节,合理选择缓存的类型和调用缓存的时机非常重要。

我们知道内存运算速度快于远程连接,所以存储上来说效率如下 内存 <= ehcache < redis <= memcached < mysql 可以看出,尽量少的远程连接,常规覆盖数据库访问的缓存,都能提高程序的性能。

要根据不同缓存的特性和原理,才能根据业务选出最合适的,来看看几种常用的缓存
1. varnish,可以作为反向代理,缓存一些资源,例如可以把struts,freemarker动态生成的页面存储起来,达到直接挡掉到达web服务器的请求。
2. ehcache,主要存储在当前机器内存中,存取非常快,缺点是内存有限,各台机器内存中各存一份,失效时间不一致,数据就会出现不一致,一般用来缓存不常变化,且缓存个数较少的数据。
3. memcached缓存,kv分布式缓存集群,可扩展性好,可以存储个数较多的缓存对象,也可以承接高流量的访问,读取缓存时远程连接,一般耗时也在零点几到几ms不等。
4. redis,nosql,是内存的kv存储,可以做为缓存使用,也可以持久化,它的性能和memcached相近。而redis最大的特点是一个data-structure store,这时redis官网首页介绍redis的第一句话,它可以保存list,hash,set,sorted set等数据结构,使用时和memcached区别是,它不用将数据取到客户端再做逻辑判断,而是可以直接在redis服务器上完成操作,比如查看某个元素是不是一个范围内,队列的长度有多长等。redis可以用来做分布式服务器的进程间的通信,比如我们经常有需要分布式锁的场景,控制同一个用户发券的并发等。







请到「今天看啥」查看全文