Coder Social home page Coder Social logo

suyeq / steammall Goto Github PK

View Code? Open in Web Editor NEW
28.0 3.0 9.0 6.27 MB

基于SpringBoot+Mybatis开发的主从架构的Steam商城,详情请看README

License: MIT License

Java 13.25% CSS 46.17% JavaScript 20.58% HTML 16.82% TSQL 3.19%
redis mq springboot mybatis master-slave-replication

steammall's Introduction

项目介绍

这个项目是主要设计缓存的一个练手项目,目前后台还没有实现,还在开发(现在已上传后台),但是前台流程是通了的,从登陆到购买以及秒杀。目前主要模块有五个:用户模块,游戏模块,评论模块、购物车模块以及秒杀模块。你们可以接着把这个项目写下去,里面注释写了很多,相信大家也能看懂,页面是直接在steam趴下来修改了的,嘿嘿嘿。。。。后台用的H-UI界面,上述模块的可视化操作全部实现了。

项目架构图

项目展示

压力测试

服务器是学生服务器,就是腾讯那个10元的服务器,在本地利用jmeter压测工具设置5000个线程、10000个请求时,首页的QPS为1024,而秒杀接口则为1678,可能服务器的问题,我感觉QPS不应该这么低。

项目的运行

在数据库中创建steam库,然后导入sql文件,修改相应的的配置,关于主从配置请自行百度啦,运行起项目,然后需要把GameService类以及CommentService类里面的afterPropertiesSet方法里面的代码注释掉,这是第一次启动加载缓存的代码。

架构以及详细实现

1.登录注册

  • 两次md5,对密码加密
  • 分布式session,将用户的登录信息缓存在redis中
  • 权限检查,每次操作在权限允许下才能进行
  • 注册,需要邮箱验证码,邮箱验证码会在缓存中存在90s的时间

2.页面数据

  • 首页及其他页面因为读多写少,利用Mysql主从复制实现读写分离,写入在主Mysql下进行,读取在从Mysql进行
  • 关于数据的不一致性,可以在写入的时候先写入缓存,读取的时候也先在缓存中读取,这样就可以避免数据的不一致性
  • 缓存利用Redis,内存满的情况下,键的删除策略采用volatile-lru
  • 热卖榜以及排序功能依据Redis的zset实现,缓存时间为30s
  • 为了减少网络时延的影响,引入了redis的管道技术,实行批处理
  • 为了更好地加快性能,在redis缓存层之上加了加了一层本地的缓存

3.秒杀功能

原理:尽量减少Mysql的访问

  • 将先将需要秒杀的数据缓存在Redis中,在秒杀接口里做预减少库存
  • 判断秒杀订单里有无对应的信息,有则秒杀重复
  • 将user信息与秒杀资源信息加入消息队列中
  • 消息接受者减少库存,新增秒杀订单
  • 客户端不断轮询缓存,查询到对应的秒杀订单,则秒杀成功

秒杀的一些优化(借鉴了网上的思路):

  • 增加了秒杀的随机路径,防刷
  • 在秒杀开始前需要验证码输入,延缓压力
  • 利用redis的缓存,限制每个用户的每分钟的秒杀次数

4.页面的渲染

  • 页面的渲染采取了jquery加ajax技术的字符串拼接以及thymleaf模板的渲染
  • 大部分是用的字符串拼接,只有少部分采用的模板渲染
  • 前端主要是由字符串拼接,后台主要是模板渲染

5. 主从配置

继承AbstractRoutingDataSource类,重写determineCurrentLookupKey方法,改变DataSource路由中介,在运行当中根据自定义KEY值动态切换真正的DataSource:

public class DynamicDataSource extends AbstractRoutingDataSource {
    
    ......
    
    @Override
    protected Object determineCurrentLookupKey() {
        Object key = "";
        //主库
        if (DynamicDataSourceHolder.isMaster()) {
            key = DynamicDataSourceHolder.MASTER;
        } else {
            //从库
            key = getSlaveKey();
            //key=DynamicDataSourceHolder.SLAVE;
        }
        logger.info("==> select datasource key [{}]", key);
        return key;
    }

    public void setSlaveDataSources(List<Object> slaveDataSources) {
        this.slaveDataSources = slaveDataSources;
    }

    ......
}

再利用AOP技术动态的改变数据源键值,就可以达到动态的分发数据请求了:

/**
 * Created with IntelliJ IDEA.
 *
 * @author: Suyeq
 * @date: 2019-04-25
 * @time: 15:23
 */
@Component
@Aspect
public class DynamicDataSourceAop {


    Logger log= LoggerFactory.getLogger(DynamicDataSourceAop.class);
    /**
     * 切面service包下的所有以add形式开头的方法
     */
    @Before("execution(* com.example.steam.service.*.add*(..))")
    public void dynamicDataSourceAddMethod(){
        log.info("设置为主节点");
        DynamicDataSourceHolder.putDataSource(DynamicDataSourceHolder.MASTER);
    }

    @Before("execution(* com.example.steam.service.*.update*(..))")
    public void dynamicDataSourceUpdateMethod(){
        log.info("设置为主节点");
        DynamicDataSourceHolder.putDataSource(DynamicDataSourceHolder.MASTER);
    }

    @Before("execution(* com.example.steam.service.*.delete*(..))")
    public void dynamicDataSourceDeleteMethod(){
        log.info("设置为主节点");
        DynamicDataSourceHolder.putDataSource(DynamicDataSourceHolder.MASTER);
    }

    @Before("execution(* com.example.steam.service.*.find*(..))")
    public void dynamicDataSourceFindMethod(){
        log.info("设置为从节点");
        DynamicDataSourceHolder.putDataSource(DynamicDataSourceHolder.SLAVE);
    }

}

6.消息队列

在项目里,利用redis的list来实现了一个简单的消息队列,用来异步处理邮件任务以及秒杀任务,在线程池中提交一个不断循环从list中取出事件的任务,调用对应的消息处理器处理:

        ......
        
        threadPoolExecutor.execute(new Runnable() {
            @Override
            public void run() {
                while (true){
                    Event event=redisService.rpop(MQKey.MQ,Event.EVENT_KEY,Event.class);
                    if (event==null){
                        continue;
                    }
                    if (!eventMap.keySet().contains(event.getEventType())){
                        log.error("未知的事件类型");
                        continue;
                    }
                    for (EventHandle eventHandle:eventMap.get(event.getEventType())){
                        threadPoolExecutor.execute(new EventHanleThread(event,eventHandle,applicationContext));
                    }
                    /**
                     * 每隔500毫秒取一次
                     */
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

steammall's People

Contributors

suyeq avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

steammall's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.