高并发架构

在业务的最初期,由于业务和用户的体量比较小,可能采用单机就足够了。随着业务的增长,用户量和并发请求量都会不断上升。当增长到一定的瓶颈的时候,系统能否抗住压力,就需要采取一些方案了。这就是著名的C10K,甚至C100K,C1000K的问题。

一般我们会从2个层面去解决这些问题:硬件层面和软件架构层面。

硬件层面

硬件层面,我们可以进行纵向扩展和横向扩展。

纵向扩展就是增加硬件的性能和配置。这个很好理解,比如采用配置更高的服务器设备和更大带宽的网络,数据库采用Oracle。纵向扩展实施起来简单,缺点是费钱;而且硬件的性能都有上限,最终还是要靠横向扩展。

横向扩展就是购买多台机器,通过负载均衡来提供服务。比如:1台不行就10台,10台不行就100台。数据库也是,数据量太大就分库分表。

软件架构层面

软件层面可以细分为很多方面,比如缓存,消息队列,数据库优化,微服务架构。

对于大多数系统,数据库都是“压倒骆驼的最后一根稻草”,是最容易引起瓶颈的问题所在。我们从架构层面尽量减少到达数据库的访问。

缓存其实就是将高频访问的数据进行缓存,获取的时候先从缓存中取,然后返回给客户端;这样就大大减少了对数据库的访问次数。缓存是成本最低,见效最高的一种方案,也是今天重点学习的内容。

消息队列可以用来应对秒杀场景的高并发,我们将所有的请求看做消息存储到消息队列,然后立即返回给客户端。然后在按照顺序从队列中取消息,一条一条的处理;可以避免系统在海量并发下造成崩溃。

数据库优化其实就SQL技巧和索引的优化了;也可以采用适合应用场景的数据库。比如如果没有事务要求,可以采用性能更高的NoSQL数据库(比如MongoDB);如果有大量的搜索需求,可以采用ElasticSearch。

微服务架构是将单体架构进行拆分,可以更好的优化具有性能瓶颈的服务,提升单个服务的性能。

Redis使用

介绍

Redis是目前最流行的缓存数据库,它将数据存到内存中,并支持持久化;所以读取速度非常快,普通机器也能轻松达到10w+/s;并支持丰富的数据类型,如key/value,list,map,set等。

官网:https://redis.io/

中文网站:http://www.redis.net.cn/

redis-cli使用

redis-cli是Redis提供的命令行客户端,可以方便执行Redis命令。简单演示命令行的操作:

  • get/set
  • del xxx
  • rpush/lrange

node_redis客户端

Redis有各种语言的客户端实现,就像我们使用MySQL驱动连接MySQL数据库一样,我们需要使用NodeJs的Redis客户端去操作Redis数据库。在NodeJs中最为好用的是node_redis实现。

node_redis:https://github.com/NodeRedis/node_redis

具体做法是:先将热点数据存储到Redis中,业务模块取数据的时候优先从缓存中获取。

代码演示热数据的准备和从缓存中取数据:

'use strict'
require('./db')
let redis = require('redis');
let util = require('util');
let client = redis.createClient('redis://127.0.0.1:6379');
let getAsync = util.promisify(client.get).bind(client)
let lrangeAsync = util.promisify(client.lrange).bind(client)
let existsAsync = util.promisify(client.exists).bind(client) client.on('error', err=>{
console.log('redis connect fail: ' + err.toString());
}); let Product = require('./model/product');
// 将商品的数据取出来,放入redis中
async function prepareHotData() {
let list = await Product.find(); let key = "product";
let data = list.reverse();
data.forEach( d=>{
client.lpush(key, JSON.stringify(d))
})
}
// 数据的准备可以在项目启动时进行,或者访问频次少的时间段
// prepareHotData() async function getProductsByPage(page = 1) {
let hasProduct = await existsAsync('product')
if(hasProduct===1){
let skip = (page-1)*5;
let limit = skip+5 - 1;
let res = await lrangeAsync('product', skip, limit)
console.log(res);
}else {
// 从数据库中获取
} } getProductsByPage(1);

NodeJs06 高并发的更多相关文章

  1. [ 高并发]Java高并发编程系列第二篇--线程同步

    高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...

  2. 如何在高并发分布式系统中生成全局唯一Id

    月整理出来,有兴趣的园友可以关注下我的博客. 分享原由,最近公司用到,并且在找最合适的方案,希望大家多参与讨论和提出新方案.我和我的小伙伴们也讨论了这个主题,我受益匪浅啊…… 博文示例: 1.     ...

  3. 协程--gevent模块(单线程高并发)

    先恶补一下知识点,上节回顾 上下文切换:当CPU从执行一个线程切换到执行另外一个线程的时候,它需要先存储当前线程的本地的数据,程序指针等,然后载入另一个线程的本地数据,程序指针等,最后才开始执行.这种 ...

  4. mysql高并发和表类型

    高并发:http://www.cnblogs.com/wangchaozhi/p/5061378.html 表类型:http://www.xiaoxiaozi.com/2009/07/14/1171/

  5. 分布式大数据高并发的web开发框架

    一.引言 通常我们认为静态网页html的网站速度是最快的,但是自从有了动态网页之后,很多交互数据都从数据库查询而来,数据也是经常变化的,除了一些新闻资讯类的网站,使用html静态化来提高访问速度是不太 ...

  6. PHP uniqid 高并发生成不重复唯一ID

    http://www.51-n.com/t-4264-1-1.html PHP uniqid()函数可用于生成不重复的唯一标识符,该函数基于微秒级当前时间戳.在高并发或者间隔时长极短(如循环代码)的情 ...

  7. 【实战Java高并发程序设计 7】让线程之间互相帮助--SynchronousQueue的实现

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...

  8. 【实战Java高并发程序设计6】挑战无锁算法:无锁的Vector实现

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...

  9. 【实战Java高并发程序设计 5】让普通变量也享受原子操作

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...

随机推荐

  1. django验证码功能

    1.目的 现在我们一般访问网页都需要输入验证码,比如博客园,有的甚至是通过手机验证码实时登录.这样做的目的主要还是为了防止其他人的恶意访问,比如爬虫,下面就来看看验证码是如何实现的 2.StringI ...

  2. Linux 中将用户添加到指定组的指令

    将一个已有用户 testuser 增加到一个已有用户组 root 中,使此用户组成为该用户的附加用户组,可以使用带 -a 参数的 usermod  指令.-a 代表 append, 也就是将用户添加到 ...

  3. 分页查询关键代码 多条件查询关键代码 删除选中商品关键代码 修改要先回显再修改 修改要先回显再修改 同一业务集中使用同一servlet的方法

    分页查询关键代码: 通过servlet转发回来的各种信息进行分页的设计(转发回的信息有 分页查询的List集合 查询的页码 查询的条数 查询的数据库总条数 查询的总页码) 从开始时循环10次出现十个数 ...

  4. Android学习<2>

    Android自学资料汇总 资料参考地址: http://blog.csdn.net/guolin_blog/article/details/26365913 http://drakeet.me/an ...

  5. Java的按值传递和按引用传递解说

    在网上看到的一个帖子解释Java的按值传递和按引用传递,感觉挺全面,就转过来,以供以后学习参考: 1:按值传递是什么 指的是在方法调用时,传递的参数是按值的拷贝传递.示例如下: public clas ...

  6. Centos7 使用LVM进行新加磁盘管理

    centos7使用LVM管理一块新的磁盘   注意!文中凡是带#的都是命令标志.   一些重要概念: LV(Logical Volume)- 逻辑卷, VG(Volumne Group)- 卷组, P ...

  7. 协议 - OSI七层网络协议模型

    摘自:https://www.cnblogs.com/oneplace/p/5611094.html 互联网协议 本文全文转载阮一峰老师的两篇文章,自己做了一些添加内容 参考:互联网协议入门(一) 互 ...

  8. eCharts.js使用心得

    最近刚刚做了一个项目,需求是使用eCharts实现实时监控,可以动态的增加和删除数据,可以全屏展示,趁着现在还没忘干净,整理一下使用过程中出现的问题和经验.可能有分析的不到位的地方,不喜勿喷! 一.图 ...

  9. HTML5--定义区块

    1.效果图如下: 备注: <article> 1.作用:用来表示文档.页面中独立的.完整的.可以独自被外部引用的内容 2.一般有个header元素,有时还有脚注 <article&g ...

  10. centos7 php7 安装php扩展

    yum install php70w.x86_64 php70w-cli.x86_64 php70w-common.x86_64 php70w-gd.x86_64 php70w-ldap.x86_64 ...