目前只考虑了后台对于秒杀系统的处理,前端尚未完善.
版本1
处理流程
前端请求秒杀接口 --> 判断用户是否已进行请求,若是则返回失败 --> 在缓存( redis )中减少库存,不成功则返回 --> 发送消息到消息队列 --> 消息消费者监听消息,更新数据库.
解决的问题
1.把商品库存量放到缓存中,每次系统启动根据消息队列中尚未消费的消息数和数据库中的库存量更新缓存中的库存量,从而降低对数据库的读取压力,且提高速度.
2.服务器故障后,由于会自动更新缓存中的库存量,解决了缓存和数据库中的库存不一致问题.
3. acitvemq 宕机
采用主从热备的方式,并将 activemq 持久化到数据库. ( 因为消费者一直在消费,如果消费完了就不会持久化到数据库,所以如果消费者不出问题,那么数据库操作的速度限制还是没有的 )
如果 activemq1 宕机了,服务会自动切换到 activemq2 ,并且会把1中的所有未消费队列持久化到 db ,所以不会出现 1 宕机导致1中剩余的未消费队列丢失的情况.(测试过的)
4.redis 宕机
采用 sentinel 对 redis 进行双机热备.(不过切换主备太慢了)
sentinel 配置参考: https://blog.51cto.com/luyx30/1350832
采用了 redis + redis sentinel 来搭建.有如下问题:
1)切换速度慢导致数据丢失和客户连接超时 (redis sentinel 可以自己调节判断下线的超时参数,但是不能调地太小,避免因为网络不畅通导致的误判)
2)切换时若两台机器 ip 不同,则ip会变化,客户需要再次获取 redis ip. (我现在为一台机器上,所以没有这个问题.)
3)如果程序挂了,则 redis 主从无法切换,整体就挂了.
本来是打算用 keepalived + redis 来搭建的,不知道两者速度对比如何.
5.服务器宕机
用 nginx 负载均衡3个服务器,大概能增加到2.5万并发(在本机开线程测试)
尚未解决的问题
1.nginx 宕机
我发现这就是一环套一环,每个都要考虑... nginx 作为第一个入口,绝对不能宕机.打算用 keepalived + 2 个nginx 来做主备.
放弃了,keepalived 是基于 VRRP 来实现的,要多台主机.
实现方式和原理可参考以下:
https://blog.csdn.net/l1028386804/article/details/80098334
https://www.cnblogs.com/kaituorensheng/p/4889268.html
2.nginx 和 okhttp 配合
nginx 搭好了,但是用 okhttp 去测试的时候会报错:
Caused by: java.io.EOFException: \n not found: limit=0 content=…
at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:240)
at okhttp3.internal.http1.Http1Codec.readHeaderLine(Http1Codec.java:226)
at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:202)
... 19 more
java.io.IOException: unexpected end of stream on Connection{localhost:8086, proxy=DIRECT hostAddress=localhost/127.0.0.1:8086 cipherSuite=none protocol=http/1.1}
不用 nginx 的时候会不会报,不知道什么原因.
版本二
1.redis集群共享一个原子键可改为把秒杀数量均分到不同的redis主机上(减少分布式一致性的牵制)
2.通过在redis中incr和decr来实现秒杀数量的减少,可以通过排队机制代替。例如使用list,把先到的用户信息塞进去,后续可以异步处理。
3.前端减少请求量到后台,大部分请求可以通过js(或其他)随机拒绝。