mysql数据库怎么解决高并发问题

发布网友

我来回答

3个回答

懂视网

php+redis实现令牌桶算法代码:

<?phpnamespace ApiLib;/**
 * 限流控制
 */class RateLimit{
 private $minNum = 60; //单个用户每分访问数
 private $dayNum = 10000; //单个用户每天总的访问量

 public function minLimit($uid)
 {
 $minNumKey = $uid . '_minNum';
 $dayNumKey = $uid . '_dayNum';
 $resMin = $this->getRedis($minNumKey, $this->minNum, 60);
 $resDay = $this->getRedis($minNumKey, $this->minNum, 800);
 if (!$resMin['status'] || !$resDay['status']) {
  exit($resMin['msg'] . $resDay['msg']);
 }
 }

 public function getRedis($key, $initNum, $expire)
 {
 $nowtime = time();
 $result = ['status' => true, 'msg' => ''];
 $redisObj = $this->di->get('redis');
 $redis->watch($key);
 $limitVal = $redis->get($key);
 if ($limitVal) {
  $limitVal = json_decode($limitVal, true);
  $newNum = min($initNum, ($limitVal['num'] - 1) + (($initNum / $expire) * ($nowtime - $limitVal['time'])));
  if ($newNum > 0) {
  $redisVal = json_encode(['num' => $newNum, 'time' => time()]);
  } else {
  return ['status' => false, 'msg' => '当前时刻令牌消耗完!'];
  }
 } else {
  $redisVal = json_encode(['num' => $initNum, 'time' => time()]);
 }
 $redis->multi();
 $redis->set($key, $redisVal);
 $rob_result = $redis->exec();
 if (!$rob_result) {
  $result = ['status' => false, 'msg' => '访问频次过多!'];
 }
 return $result;
 }}

代码要点:

1、首先定义规则

单个用户每分钟访问次数($minNum),单个用户每天总的访问次数($dayNum),接口总的访问次数等不同的规则。

2、计算速率

该代码示例以秒为最小的时间单位,速率=访问次数/时间($initNum / $expire)

3、每次访问后补充的令牌个数计算方式

获取上次访问的时间即上次存入令牌的时间,计算当前时刻与上次访问的时间差乘以速率就是此次需要补充的令牌个数,注意补充令牌后总的令牌个数不能大于初始化的令牌个数,以补充数和初始化数的最小值为准。

4、程序流程

第一次访问时初始化令牌个数($minNum),存入Redis同时将当前的时间戳存入以便计算下次需要补充的令牌个数。

第二次访问时获取剩余的令牌个数,并添加本次应该补充的令牌个数,补充后如何令牌数>0则当前访问是有效的可以访问,否则令牌使用完毕不可访问。先补充令牌再判断令牌是否>0的原因是由于还有速率这个概念即如果上次剩余的令牌为0但是本次应该补充的令牌>1那么本次依然可以访问。

5、针对并发的处理

使用Redis的乐观锁机制。

更多相关知识,请关注 PHP中文网!!

热心网友

限流算法目前程序开发过程常用的限流算法有两个:漏桶算法和令牌桶算法。

漏桶算法

漏桶算法的原理比较简单,请求进入到漏桶中,漏桶以一定的速率漏水。当请求过多时,水直接溢出。可以看出,漏桶算法可以强制*数据的传输速度。如图所示,把请求比作是水滴,水先滴到桶里,通过漏洞并以限定的速度出水,当水来得过猛而出水不够快时就会导致水直接溢出,即拒绝服务。

图片来自网络

漏桶的出水速度是恒定的,那么意味着如果瞬时大流量的话,将有大部分请求被丢弃掉(也就是所谓的溢出)。

令牌桶算法

令牌桶算法的原理是系统以一定速率向桶中放入令牌,如果有请求时,请求会从桶中取出令牌,如果能取到令牌,则可以继续完成请求,否则等待或者拒绝服务。这种算法可以应对突发程度的请求,因此比漏桶算法好。

图片来自网络

漏桶算法和令牌桶算法的选择

两者的主要区别漏桶算法能够强行*处理数据的速率,不论系统是否空闲。而令牌桶算法能够在*数据的平均处理速率的同时还允许某种程度的突发流量。如何理解上面的含义呢?漏桶算法,比如系统吞吐量是 120/s,业务请求 130/s,使用漏斗限流 100/s,起到限流的作用,多余的请求将产生等待或者丢弃。对于令牌桶算法,每秒产生 100 个令牌,系统容量 200 个令牌。正常情况下,业务请求 100/s 时,请求能被正常被处理。当有突发流量过来比如 200 个请求时,因为系统容量有 200 个令牌可以同一时刻处理掉这 200 个请求。如果是漏桶算法,则只能处理 100 个请求,其他的请求等待或者被丢弃。

热心网友

通常情况下在PHP中MySQL查询是串行的,如果能实现MySQL查询的异步化,就能实现多条SQL语句同时执行,这样就能大大地缩短MySQL查询的耗时,提高数据库查询的效率。目前MySQL的异步查询只在MySQLi扩展提供,查询方法分别是:
1、使用MYSQLI_ASYNC模式执行mysqli::query
2、获取异步查询结果:mysqli::reap_async_query
使用mysql异步查询,需要使用mysqlnd作为PHP的MySQL数据库驱动。
使用MySQL异步查询,因为需要给所有查询都创建一个新的连接,而MySQL服务端会为每个连接创建一个单独的线程进行处理,如果创建的线程过多,则会造成线程切换引起系统负载过高。Swoole中的异步MySQL其原理是通过MYSQLI_ASYNC模式查询,然后获取mysql连接的socket,加入到epoll事件循环中,当数据库返回结果时会回调指定函数,这个过程是完全异步非阻塞的。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com