电商网站项目总结(分布式多模块+SSM+Mysql+Redis+ActiveMQ)
一. 电商项目系统架构
①parent:所有模块都继承于它,被打包成pom。Maven依赖项基本都放在这里面,除了每个项目运行的Tomcat和jetty插件,这些插件放在模块的pom.xml中
②core:除parent之外,所有模块都依赖于它,被打包成jar。这里存放所有模块公用的一些工具包,如全局异常处理,JedisService类,前台和后台数据传输的结果集封装,公用的Bean等等
③admin:后台管理模块,处理商品信息上传,商品上下架,类别信息编辑等等
④front:前台模块,普通用户所看到的一些业务,如书籍详情,评论,支付等业务。
⑤sso:单点登录模块,处理用户的登录和注册,包括手机短信验证码验证。
二. 各模块之间的关系
①远程调用:前台模块远程调用后台的接口获取数据库信息,HTTPClient与Dubbo都可以实现远程调用,只是HttpClient在客户端编程模拟浏览器请求去获得数据,需要配置较多参数,还需要处理返回值。而Dubbo提供面向本地接口一样的远程调用,更为方便。短信验证码使用互亿无线的短信服务,调用服务使用的是HTTPClient,电话号码和服务器端生成的验证码作为参数传递过去,等待用户接受到短信内容输入验证码传入后台就可以对其进行验证码匹配。
②消息队列:前台模块通过远程调用的到的数据会存储在Redis数据库中,这样在下次请求数据的时候就可以直接先访问缓存中有无数据再访问后台的Mysql数据库。此时Redis和Mysql都有了一份数据,当后台更改了商品信息之后,需要及时通知前台的缓存数据删除。这里使用的是ActiveMQ来通知前台后台数据已经更改,期望前台将缓存数据清除。
③Nginx服务器:静态资源代理和反向代理,在本地就可以实现访问不同的域名来访问不同的模块,静态资源主要是图片的代理。
④跨域请求:单点登录模块是没有页面的,登录和注册页面也是在前台模块的。前台模块登录页面的请求单点登录模块就会是跨域的请求,这里是通过Jsonp解决跨域问题的。注意一下下图,请求参数是用户名和密码的时候我们是直接去Mysql中查询用户,最后返回结果并缓存用户信息,这里Redis缓存中的key是token(UUID生成的随机字符串),类似于sessionid,访问其他系统只需要携带上token参数就可以直接访问Redis缓存查询用户是否登录了。
三. 数据库相关问题(Mysql+Redis)
Ⅰ. 数据库优化
①索引优化:Mysql会在我们建表的时候就为主键建立索引,我们还可以手动为经常需要查询的列建立索引,如用户名和密码建立复合索引
②大字段垂直拆分:将单表的访问较少的大字段列拆分出来作为另一张表,两标增加了商品ID联系,减少查询的IO操作(数据库记录按照记录存放,访问其它字段是大字段也会被访问到)。如商品表的详情项
③关联取消:取消每张表的外键关联,代码层次实际上已经保证了数据库的参照完整性。如插入商品操作,其中的类别是类别表的主键,商品的类别选择项实际上就是从类别表里面读取出来的,自然就不需要数据库再去检查参照完整性了
④适度冗余减少表的连接操作:如评论表存储用户id就可以找到唯一的用户,但是在显示评论的时候,我们需要显示用户名,此时就需要去查找用户表,为了减少这一步,可以将用户名存储在评论表中。通过增加用户名的冗余来减少了评论表和用户表的连接操作。用户id也是不可以去掉的,毕竟点击用户名一般是可以跳转到用户主页的。现在如果用户更新用户名就需要同时维护评论表了,不过相对于用户更改用户名,评论查询就要频繁得多。
⑤数据类型选择:商品价格使用整数而不是浮点数存放,浮点数的本身就不是一个精准的数字,而整数和浮点数可以通过乘以一个固定的系数相互转换,这样可以解决数据不精确的问题,还可以让数据的处理更为高效
Ⅱ.Redis
①令牌存储:不能直接将用户名作为key存储,那样在另外的浏览器登陆验证的时候即使密码不正确验证用户名正确就可以成功登陆了,那显然是错误的。令牌使用hash存储,{token,user}为一个键值对,redis存储的是user转化为Json的字符串,设置失效时间,每次token查询会更新失效时间