实战:从零开始搭建弹性应用

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 作者:轶俗

一、背景介绍

(一)课程预览

1.png

Ø  What

基于Spring boot 框架 + Cassandra数据库,实现一个支持海量用户 的用户管理系统。

Ø  Why

Spring Boot大幅简化了应用搭建和开发的成本,Cassandra作为开源分布式数据库,既具备NoSQL数据库高性能,高可用,海量无限扩展的特点,又具备类似关系型数据库的数据模型,非常适合开发在线应用。

Ø  Who

Web开发入门者,希望深入了解Cassandra设计和使用的用户。

Ø  How

本文将从设计开始,手把手教用户实现一个用户管理系统

 

(二)Spring Data for Cassandra简介

1.Cassandra

- 去中心化,海量数据扩展能力;

- Zero Down Time

- 支持二级索引,物化视图,集合等实用功能;

- AppleNetflix360,华为等大公司广泛采用。

 

2.Spring Data

- 强大的存储库和灵活的抽象映射;

- 便于与Spring MVC controller 集成;

- 支持MySQLRedisRedisESCassandra等数据库。

 

3.Spring Data for Cassandra

- 降低CQL语言的学习成本,提升开发速度;

- 支持同步,反应式和异步等多种模式;

- 支持用户自定义复杂查询;

- 一套代码支持MySQL冷热分离,ES加速查询,Redis缓存等多种玩法。

 

(三)准备工作

准备工作主要分为以下三个步骤:

1.  购买Cassandra集群

1)购买Cassandra云服务

2)用户密码:云Cassandra控制台-> 集群详情->账号管理页面

3)链接URL:在数据库连接页面

3.png

2.  配置集群

1)  Cassandra控制台 -> 集群详情-> 数据库连接页面开通公网链接

2)  Cassandra控制台-> 集群详情-> 数据安全页面配置本机IP到白名单

 

3. 配置开发环境

1)下载并安装Idea开发环境

2)Spring模版生成器中生成项目模版

地址:https://start.spring.io/

3)将生成好的项目导入Idea

当完成上述步骤后,用户可以获得一个工程,如下所示:

6.png

这个工程是空的,里面只有一个Main函数可以执行,其他功能需要后续操作进行添加。

 

二、系统设计

(一)需求分析

需求分析主要分为三部分:数据需求、功能需求和其他需求。

 

1.数据需求

3.png

由于要做的是用户管理系统,用户的数据存储在Cassandra数据库中。用户数据可分为以下几个属性:用户ID、用户名、密码与用户年龄,后续可根据需求扩展更多用户信息,例如email,电话号码,住址等。

 

2.功能需求

7.png

功能一般分为增删改查4个部分。

增指的是在系统中增加一个新的用户,删指的是把用户信息删除,改指的是修改用户信息,查则较为复杂。查询可以包含很多场景,例如基于用户ID查询,基于用户年龄查询,或者要展示全部用户的信息。

 

3.其他需求

除了上述基本功能需求外,还需要注意以下四点:

1)高并发高性能

用户可能会频繁更新同一条数据,或者系统需要支撑100万个用户同时注册的场景,或者当有1亿个用户的时候,能不能快速展示全部用户,以上都属于高并发高性能场景。

2)可扩展性

系统功能在设计初期,可能有一些地方没有考虑到,例如初期没有设计通过电子邮箱地址搜索用户的功能,后续有需求需要添加这个功能,因此对可扩展性有一定的要求。

3)开发敏捷

系统最开始的功能可能开发起来并不会特别复杂,但随着系统的累加,功能会越来越复杂,因此需要注意开发敏捷性。

4)美观

该系统作为外部服务,会存在与用户交互的界面,因此希望这个界面对用户足够友好。

 

(二)Schema设计

需求完成后,我们接下来需要做的事情是设计一个Schema

这里需要注意,一定要先完成Schema的设然后再去实现功能,否则可能会导致系统性能会出现一些瓶颈。

9.png10.png

分析刚才的数据,由于ID字段是唯一的,因此可以把ID字段放在主键的位置。

主键有几个要求,首先要符合用户查询常见维度,例如上方提到的用户查询,有可能通过用户ID、年龄等信息进行查询。

ID作为主键而不是年龄的原因在于,一方面是年龄的区分度不够,很多用户拥有同样的年龄,如果以年龄做主键的话,可能会导致相同年龄的数据很多,必然要年龄后面再结合一个其他字段去保证主键的唯一。

其次,年龄作为主键可能会存在热点问题,比如所有的用户都是20~25岁,那么数据都会集中在分片,导致分片非常不均匀。

那么,把ID放在主键是不是就可以解决这些问题了呢?

这要看ID本身是否足够打散,如果是随机生成一些ID,则数据本身非常均匀。如果ID是自增的,这对于Cassandra来说并不是一个特别好的选择。对于CassandraID,我们希望尽可能去打散。当然,如果说ID把它放在Partition Key的话,因为它本身是有一些哈希可以去做打散的,因此也是可行的。

但是如果把ID放在Partition Key的话,Partition Key本身是不做排序,因此想查询ID5~100范围内的所有用户,这个查询无法实现。由于这次的系统设计较为简易,没有排序的要求,因此设计当中没有包含这项功能。

除此之外,有一个基于age字段做查询,age字段不在主键中出现。如果现在不对它建一个二级索引,它本身会转化成一个过滤逻辑,类似于全表扫描,如果数据量较小则没有问题。由于设计的目标是一个较大的用户管理系统,数据存储可能是几千万条甚至几亿条,在这些数据当中过滤出来年龄符合一定要求的存在一定难度,因此建一个二级索引加速查询。

创建二级索引的DDL如下所示:

15.png

(三)CQL设计

CQL设计遵循增删改查原则,实现方式如下。

1.

insert into test_keyspace.user(id, age, username, password) values(20, 18,'apple','banana');

2.

可以根据具体id进行删除,如:

delete from test_keyspace.user where id=20;

3.

更改分为两个部分,第一部分是更改的字段,第二部分是更改的数据,如要把id2的用户年龄改为20,则实现语句如下:

update test_keyspace.user set age=20 where id=2;

 

4.

查询分为多个方式,如果查询所有数据,则:

select * from test_keyspace.user ;

如果根据ID查询,例如id2的用户:

select * from test_keyspace.user where id=2 ;

如果根据年龄查询,例如年龄为2的用户:

select * from test_keyspace.user where age=2 ;

如果数据量少,不需要二级索引,通过年龄进行过滤查询:

select * from test_keyspace.user where age=2 allow filtering ;

n  此处必须加上allow filtering属性,否则Cassandra可能会拒绝查询。

 

 

三、编码实战

(一)代码框架

13.png

Ø  框架主要由以下几个部分构成:

1)UserController:控制层,负责与前段交互,页面跳转

2)UserService:业务层,负责处理业务逻辑

3)User RepoDAO层,负责访问数据库获取数据

4)CassandraConfig:存储Cassandra集群的访问配置

5)Resource:前端页面位置

整个代码按照MVC的设计分成数个模块。前端模块会提供三个网页,一个是list.html,用来展示User;第二个是userAdd.html,增加一个user;最后一个是userEdit.html,表示更新一个user

所有的html会把请求发到控制层和前端做交互,包括获取数据发到前端做展示,跳转到某个页面,这些都是在控制层进行。

控制层下面是业务层,传统的业务层更多的是处理一些业务的请求。我们这次的系统相对简单,业务层主要承担的作用是把DAO层的数据返回给上面的控制层。同时,业务层也会做一些简单的处理,比如统计一些用户的数目,然后将这些信息发给控制层。

最下面是DAO层,可以跟Cassandra做一一映射,负责Cassandra数据库的访问和链接。

 

(二)增删改查

1.Cassandra访问配置

15.png

在访问Cassandra之前,首先要进行访问配置。CassandraConfig本身就是在Spring Data框架里,需要继承AbstractCassandraConfiguration去定义需要的信息。

这里面包括了hostList,即数据库的连接串,这些信息可以在Cassandra管理页面找到。

第二个是keyspaceName,即访问的keyspace的具体名字。

第三个就是访问的用户名和密码,做权限的验证。

最后一个是datacenter,它其实也可以在云控制台里面去找到。在云控制台上它叫数据中心ID,不叫数据中心名称,通常情况是一个CN开头的字符串。

值得一提的是底下会有一个cassandraSession实现,它发送用户名和密码帮助Cassandra连接。

 

2.DAO

16.png

Ø  定义User对象,并指定id对应user表的PrimaryKey

完成配置后开始定义数据。刚才存的是User,这个类对应到Cassandra当中是Table表,它有4个字段,分别是IDUserNamePasswordAge。这里面有一个@PrimaryKey的定义,作用是告知Cassandra框架,ID字段是一个PrimaryKey,它是一个BIGINT。除此之外,这个实体实现了一些简单的GetSet的方法。

17.png

Ø  DAO层只需要继承CassandraRepository即可实现基本的增删改查,对于带条件的增删改查通过@Query的方式支持。

如何把实体对象真正的去与Cassandra进行读取?对于DAO层,Spring Data也做了很多事情。

如上图所示,CassandraRepository实现了很多基本的Cassandra访问,比如findAll是获取一张表里所有的数据,findAllById是可以通过ID获取一个数据,insert是插入一条数据。有了这些之后,可以实现基本的增删改操作。

如果想实现的查询比较复杂,例如基于年龄做查询,可以做一个新的interface,让userRepository继承CassandraRepository,在里面定义一种新的查询叫findByAgeSpring Data支持@Query关键词,它定义了要访问的数据。

 

3.Service

18.png

Ø  通过AutoWired标记链接DAU层;

Ø  本例子中业务逻辑比较简单,并未包括复杂的处理,实际开发过程中Service中可以处理复杂业务逻辑。

 

这里有几个需要关注的点:

第一个是类本身为@Service关键词进行标记。第二个是AutoWired属性,可以将UserRepositoryService层链接。第三个是实现了getUserNum,可以去userRepository拿到所有的数据,然后调size

 

4.Controller

19.png

Ø  @RequestMapping来映射请求,也就是通过它来指定控制器 可以处理哪些URL请求, 函数返回值标记跳转的页面地址;

Ø  返回值通过model.addAttribute返回前端。

 

(三)前端页面

19.png

前端页面的实现代码可在GitHub上查看。

左下角的add按键可以添加新用户,后右上角的EditDelete,可以对用户进行修改与删除。下方的搜索用户功能,可以根据年龄搜索用户。

 

 

四、总结

(一)功能演示

1.前端页面

20.png

2.添加用户

21.png

3.修改用户

22.png

4.按年龄搜索用户

23.png

(二)演示总结

通过上述讲解与演示,可以总结出设计系统主要有以下步骤组成:

1. 明确需求

-  需要存储什么数据

-  需要什么查询语句

2. 设计表结构

-  主键设计

-  二级索引

3. MVC实现

-  基于Model实现控制器

-  实现前端展示

n  进阶思考:

1)系统需要处理高并发,如这是一个用户点击统计,有一列是点击次数,如何能统计出用户点击的精确次数?

2)如果该用户系统需要支持100w tps/qps每秒,应该如何继续迭代?

234.png

(三)更多高级功能 - Serverless Cassandra

25.png

阿里云推出了一个新的服务叫Serverless Cassandra,核心是解决用户的资源管理成本和稳定性问题。

传统模式存在几个问题:

第一,可能用户的服务本身体量很小,如果购买数据库服务的话,起步门槛较高,成本对于用户来说不太友好。

第二,如果在使用Cassandra的过程中,用户的网站做大了,此时传统数据库需要不停地运维和规划,需要通过人为触发来扩展数据库。

第三,传统资源管理的方式需要提前规划资源,可能造成较大的资源浪费。例如用户的服务在晚上请求量较低,但在配置时需要按照高请求量场景进行配置,成本较高。

26.png

Serverless Cassandra无需任何数据库管理,实例运行于庞大的资源池 ,按使用量计费,如用电一般,随取随用,适用于不频发的、间歇性的或不可预测的工作负载。

Ø  Serverless Cassandra适用场景

1)变化或不可预测的工作负载

2)定时处理任务的场景

3)新上线应用

4)完全免运维的用户

 

Ø  Serverless Cassandra三大特性

1)简单易用

全托管,无需数据库管理;

开源标准接口,应用0 改造;

丰富生态和周边工具配套

2)经济高效

超低门槛

存储计算独立计费

按使用量计费

多存储/ 可用性级别

3)按需弹性

存储计算独立伸缩

无需容量规划,自动伸缩

相关实践学习
【文生图】一键部署Stable Diffusion基于函数计算
本实验教你如何在函数计算FC上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。函数计算提供一定的免费额度供用户使用。本实验答疑钉钉群:29290019867
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
目录
打赏
0
0
0
0
31
分享
相关文章
基于SpringBoot+Vue+uniapp的教师管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的教师管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
122 1
DDD面试题:DDD聚合和表的对应关系是什么 ?(来自蚂蚁面试)
尼恩,一位40岁的资深架构师,分享了其读者群中关于DDD(领域驱动设计)的面试题及解答,涵盖DDD架构落地、微服务拆分、聚合与MySQL表的对应关系等内容。尼恩通过系统化的梳理,帮助读者在面试中展现强大的技术实力,让面试官印象深刻。此外,他还提供了《尼恩Java面试宝典》等多本技术圣经PDF,助力读者提升架构、设计和开发水平。关注【技术自由圈】公众号,获取更多资源。
DDD面试题:DDD聚合和表的对应关系是什么 ?(来自蚂蚁面试)
怎么减小Docker的镜像体积?
**Docker 镜像优化目标:**提升构建速度、减小镜像大小、增强安全性和效率。**技巧:**1) 选择轻量级基础镜像(如Alpine、Ubuntu Minimal);2) 使用多阶段构建,分阶段复制文件和执行操作;3) 利用缓存加速构建,避免不必要的重复;4) 合并`RUN`指令减少镜像层数。这些方法能显著优化镜像,提高性能和节省存储空间。
182 0
十六年所思所感,聊聊这些年我所经历的 DevOps 系统
从 2008 年开始,我陆陆续续参与了多个 DevOps 系统的建设,如今,审视这些系统的建设初衷和它们的设计思路或遇到的问题,依然有不少借鉴意义。我会按照时间顺序,把每个 DevOps 系统的特点,诞生的背景,以及在当时所主要解决的问题做一个概要的介绍,同时,我们也会以今天的视角再次审视这些问题,来看下同样的问题,经过十几年的发展,解决方案上有哪些不同。
springboot+mybatis配置多数据源实战
一般一个项目中只会连接一个数据库.但是随着需求变更,会要求同一个项目中连接多个数据库,本文就讲一下如何在一个项目中对多个数据库进行连接.本文基于springboot+mybatis介绍如何进行多数据源连接(本文演示配置两个数据库,配置多个同理).
springboot+mybatis配置多数据源实战
首批!阿里云MaxCompute完成中国信通院基于无服务器架构大数据平台测试
近日,阿里云计算有限公司MaxCompute产品顺利完成中国信通院首批无服务器架构(Serverless)大数据平台测试。
673 7
Flink报错问题之写orc报错如何解决
Apache Flink是由Apache软件基金会开发的开源流处理框架,其核心是用Java和Scala编写的分布式流数据流引擎。本合集提供有关Apache Flink相关技术、使用技巧和最佳实践的资源。
解决nohup: 忽略输入并把输出追加到“nohup.out“或者nohup: 忽略输入重定向错误到标准输出端
解决nohup: 忽略输入并把输出追加到“nohup.out“或者nohup: 忽略输入重定向错误到标准输出端
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问