武林低手 怎么在日常工作中 思考开发架构?

360影视 欧美动漫 2025-05-20 00:44 2

摘要:高并发电商架构的核心: 在于通过缓存扛住读压力、异步化解耦写操作、分布式扩展提升系统容量。Java开发者需结合具体业务场景,灵活运用微服务、缓存、消息队列等技术,同时重视代码优化(如减少锁竞争、避免大事务)和 全链路监控,确保系统在高并发下的稳定性和可扩展性。

高并发电商架构的核心: 在于通过缓存扛住读压力、异步化解耦写操作、分布式扩展提升系统容量。Java开发者需结合具体业务场景,灵活运用微服务、缓存、消息队列等技术,同时重视代码优化(如减少锁竞争、避免大事务)和 全链路监控,确保系统在高并发下的稳定性和可扩展性。

分层与模块化

分层架构:采用表现层(如Spring MVC)、业务层(服务拆分service)、数据访问层(ORM框架)的分层设计,降低耦合性。微服务拆分:将系统拆分为用户服务、商品服务、订单服务等独立模块,每个服务可独立部署和扩展(如使用Spring Cloud或Dubbo)。

无状态化与水平扩展

通过无状态服务设计(如使用JWT Token管理会话),结合Kubernetes 或 Nginx 实现动态扩缩容,应对流量峰值。(Nginx 服务发现与负载均衡 如轮询、加权随机 分发请求)

多级缓存策略

本地缓存:使用Guava Cache或Caffeine缓存热点数据(如商品详情),减少Redis访问。分布式缓存:Redis Cluster缓存用户会话、库存信息等高频数据,通过分片和主从架构提升吞吐量(单节点QPS可达10万+)。缓存穿透/雪崩防护:采用布隆过滤器拦截无效请求,设置随机过期时间避免集中失效。

静态资源缓存

将HTML、CSS、图片等静态资源上传至CDN,减少服务器压力,提升用户访问速度。

削峰填谷

使用Kafka或RocketMQ异步处理订单创建、库存扣减等高并发写入操作。例如,用户下单请求先写入消息队列,再由消费者批量处理,避免数据库瞬时压力太大。

最终一致性保障

通过消息队列实现分布式事务(如TCC模式或Saga模式),确保订单、库存、积分等跨服务操作的最终一致性。

分库分表与读写分离

垂直分库:将用户库、商品库、订单库分离,减少单库压力。水平分表:按用户ID或订单ID哈希分片,结合ShardingSphere实现数据路由。读写分离:通过MySQL主从集群,写操作走主库,读操作走从库(如使用MyCat或ShardingSphere)。

连接池与SQL优化

使用HikariCP或Druid连接池,控制最大连接数,避免数据库连接耗尽。通过索引优化(B+树索引、覆盖索引)和慢SQL分析工具(如Arthas)提升查询效率

乐观锁与分布式锁

乐观锁:在扣减库存时,通过版本号或CAS机制防止超卖(如UPDATE stock SET count=count-1 WHERE id=1001 AND count>0)。分布式锁:使用Redisson实现分布式锁,控制对共享资源(如秒杀库存)的并发访问。

限流与熔断

限流:通过Sentinel或Resilience4j设置QPS阈值(如每秒5000次),超出阈值则拒绝请求,防止系统雪崩15。熔断降级:在服务调用失败率过高时,自动熔断并返回兜底数据(如Hystrix或Sentinel)

预扣库存与异步下单

秒杀开始前,将库存预热至Redis,用户请求时通过Lua脚本原子扣减库存,生成临时订单后异步落库。

防刷与风控

通过IP限流、验证码、用户行为分析(如使用机器学习模型)识别并拦截恶意请求

下面给出 本地缓存 实战案例 供大家参考:

package..;import com.google.common.cache.Cache;import com.google.common.cache.CacheBuilder;import com.google.common.cache.RemovalListener;import com.google.common.cache.RemovalNotification;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;import java.util.concurrent.TimeUnit;/*** @author * @title: CacheLocalConfig* @description:本地缓存 贼快* @date */@Componentpublic class CacheLocalConfigService {private static Logger logger = LoggerFactory.getLogger(CacheLocalConfigService.class);/** 缓存值的最大数 */private int maximumSize = 1000;private Cache cache = null;public CacheLocalConfigService{super;}public int getMaximumSize{return maximumSize;}public void setMaximumSize(int maximumSize){this.maximumSize = maximumSize;}/*** 初始化。*/@PostConstructpublic void init {cache = CacheBuilder.newBuilder//基于容量回收//基于容量的清除:通过 CacheBuilder.maximumSize 方法设置 Cache 的最大容量数,当缓存数量达到或接近该最大值时,将清除最近最少使用的缓存;.maximumSize(this.maximumSize).initialCapacity(100)//并发级别 设置并发级别,并发级别是指可以同时写缓存的线程数.concurrencyLevel(5)//设置多久没被访问(读/写)的过期时间 -- expireAfterAccess指定对象多久没有被访问后过期。.expireAfterAccess(60*10, TimeUnit.SECONDS)//设置过期时间(写入n秒内过期)在一定时间内没有创建/覆盖时,会移除key,下次从loading中取.expireAfterWrite(60*10, TimeUnit.SECONDS)//.removalListener(async)//设置缓存的移除通知.removalListener(new RemovalListener {@Overridepublic void onRemoval(RemovalNotification notification) {logger.error("*********CacheLocalConfigService removalListener****"+notification.getKey + " was removed, cause is " + notification.getCause);}}).recordStats.build;}/**** 获取一个缓存,如果该缓存不存在则返回一个null值* 获取{@linkplain Object}。* @return 返回{@code null}表示没有缓存*/public Object getIfPresent(String key){return this.cache.getIfPresent(key);}/*** 添加至缓存。* @param key* @param o*/public void put(String key,Object o){this.cache.put(key, o);}/*** 清除指定名称缓存。* @param key*/public void invalidate(String key){this.cache.invalidate(key);}public String stats{/* hitRate:缓存命中率;averageLoadPenalty:加载新值的平均时间,单位为纳秒;evictionCount:缓存项被回收的总数,不包括显式清除。*/return this.cache.stats.toString;}public long size{return this.cache.size;}}

跟我一起使用:

@Servicepublic class CacheLocalCommonService {private Logger logger = LoggerFactory.getLogger(CacheLocalCommonService.class);@Autowiredprivate TmanVisitAndPlanService visitAndPlanService;@Autowiredprivate CacheLocalConfigService cacheLocalConfigService;@Autowiredprivate ImanAreaService imanAreaService;public static final String key_local_cache_manForSelect = "local_cache_manForSelect_visit";public static final String key_AllProvince = "local_cache_AllProvince";public List> findmanForSelect{Object data = cacheLocalConfigService.getIfPresent(key_local_cache_manForSelect);if(data == null){List> dataSelectDb = visitAndPlanService.findmanForSelect;cacheLocalConfigService.put(key_local_cache_manForSelect,dataSelectDb);logger.error("****findmanForSelect put缓存,key={}",key_local_cache_manForSelect);return dataSelectDb;}logger.error("****使用缓存,key={}",key_local_cache_manForSelect);return (List>) data;}/*** 清除缓存*/public void cleanKeymanForSelect{try {logger.error("**** cleanKeymanForSelect invalidate缓存,key={}",key_local_cache_manForSelect);cacheLocalConfigService.invalidate(key_local_cache_manForSelect);} catch (Exception e) {logger.error("**** invalidate缓存,key={} 异常",key_local_cache_manForSelect);}}public List findAllProvinces{String key = key_AllProvince;Object data = cacheLocalConfigService.getIfPresent(key);if(data == null){List provinces = imanAreaService.findAllProvinces;cacheLocalConfigService.put(key,provinces);logger.error("****findAllProvinces put缓存,key={}",key);return provinces;}logger.error("****使用缓存,key={}",key);logger.error("****cacheLocalConfigService 缓存 统计,cacheStats={}", cacheLocalConfigService.stats);logger.error("****cacheLocalConfigService 缓存 统计,size={}", cacheLocalConfigService.size);return (List) data;}}

来源:左手小拇指

相关推荐