[投机取巧]一个单机服务的并发问题

Posted 技术改变人生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[投机取巧]一个单机服务的并发问题相关的知识,希望对你有一定的参考价值。

最近在处理一个单体应该的时候遇到了并发问题

出现并发问题的伪代码:

1         String redisKey="ORDER_CURRENT_KEY";
2         String orderCurrentKey = redisUtils.get(redisKey);
3         if (Integer.valueOf(orderCurrentKey)<100) {
4             redisUtils.incr(redisKey ,1 );
5             System.out.println("服务器只能同时处理100个请求");
6         }else {
7             System.out.println("当前同时处理数已满");
8             return null;
9         }   

压力测试的并发为每秒1000,当前线上生产环境,高峰期每秒2000,日常每秒50

伪代码第二行:

假设会进入300个同时获取,那这300个线程,就会通过第三行的判断,变为同时处理了300个请求,导致测试环境程序奔溃。

而且最终redis中的值是 ORDER_CURRENT_KEY 的值是300.

简单并发问题,测试服务器配置较低...容易出现各种问题;

想法:

解决办法有:

  • 加锁,对在获取值,到对比加锁,但是会严重影响程序的并发能力
  • 依赖redis或者zookeeper做分布式锁,redis由于知识储备问题,没有实现;依赖zookeeper,就因为一个锁,依赖多一个组件,不划算!
  • 最终,使用了一种投机取巧的办法!

看伪代码:

1      Long lockOrder = redisUtils.incr("ORDER_CURRENT_LOCK_KEY",1);
2         String redisKey="ORDER_CURRENT_KEY";
3         if (lockOrder<100) {
4             redisUtils.incr(redisKey ,1 );
5             System.out.println("服务器只能同时处理100个请求");
6         }else {
7             System.out.println("当前同时处理数已满");
8             return null;
9         }

思路是,加多一个redis键值对;

利用 redisUtils.incr(key,1);内部的计算方法!还有redis天然的单线程!

所以算出来值不会存在重复值!并发再高也不会!lockOrder值就是请求数!

lockOrder !!!既然不重复!

在第三行对比的时候,lockOrder 的值是:0-99,都会进入服务的内部处理!其他都直接返回结果!

好像完美解决!

反正现在压力测试,并没有出现过超出100的同时请求处理!

确实有点投机取巧,利用redis的单线程特性!

确实有点投机取巧,但是并不是每个公司,都会搭建集群,都部署超高配置服务器;

这里生产环境只有一台8核16G的服务器,所有服务都部署在上面,不过业务是非常简单的而已。。

可能后续会拓展吧.......什么高可用,高性能,更高并发5K-10K。。。后续再续集进行个人的知识储备吧。

 

以上是关于[投机取巧]一个单机服务的并发问题的主要内容,如果未能解决你的问题,请参考以下文章

单机高并发模型设计

单机高并发模型设计

单机高并发模型设计

单机高并发模型设计

golang代码片段(摘抄)

Swift新async/await并发中利用Task防止指定代码片段执行的数据竞争(Data Race)问题