java redis做app后台 怎么实现多人抢单
高洛峰
高洛峰 2016-11-11 10:02:25
0
1
1386

java jfinal和redis作为后台。具体流程是:

app端:app有信息展示,用户选择一条信息进入详细,然后点击抢单按钮,这时携带2个id参数发送给后台

后台:根据2个id,修改订单表的状态和用户的接单数

现在考虑高并发的问题,该怎么使用redis的队列呢?

我试过使用redis 在创建订单时把订单id存入redis

@ActionKey("/order/create")
    public void order_create(){

        Order order = Order.dao.order_create(map);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("rs", order.result);
        jsonObject.put("msg", StateDict.dataBaseMsg(order.result));

        Cache c = Redis.use("order");
        c.rpush("orderlist", order.id);
        renderJson(jsonObject);

    }

然后在app点击抢单按钮时读取redis

@ActionKey("/order/take")
    public void order_take(){
        Integer id = getParaToInt(0);
        Integer uid = getParaToInt(1);
        
        Cache orderCache = Redis.use("order");
        Object orderlist = orderCache.lpop("orderlist");
        
        JSONObject json = new JSONObject();

        if(orderlist!=null){
            int rs = Order.dao.order_take(id,uid);
            json.put("rs", rs);
            json.put("msg", StateDict.dataBaseMsg(rs));
        }else{
            int rs = StateDict.ORDER_TAKEN;
            json.put("rs", rs);
            json.put("msg", StateDict.dataBaseMsg(rs));
        }

        renderJson(json);
    }

但是我模拟多并发时,同一个用户可以接多次单,也就是用户的接单数不是1次而是多次,
求高手看看 我该怎么写,
我对redis也不是太熟 刚开始使用

这时操作数据库的代码

public int order_take(int id,int uid){
        
            int state = Db.queryInt("SELECT t.state FROM t_order t WHERE t.id=?", id);
            //多个请求同时进来的时候state都是0,所以都会进入if条件
            if(state==0){
                int rs1 = Db.update("UPDATE t_order SET taketime=?,takeuserid=?,state=? WHERE id=?", User.dao.getSysTime(),uid,1,id);
                if(rs1>0){
                    int rs2 = Db.update("UPDATE t_user SET takecount=takecount+1 WHERE id=?",uid);
                    if(rs2>0){
                        return StateDict.DATABASE_SUCCESS;
                    }else{
                        return StateDict.DATABASE_FAIL;
                    }
                }else{
                    return StateDict.DATABASE_FAIL;
                }
            }else{
                return StateDict.ORDER_TAKEN;
            }
    }


高洛峰
高洛峰

拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...

全部回复(1)
三叔

没太看懂你的代码表达的意思,感觉跟你的描述不太相符。

用redis也不是不可以,但效率可能有点低,建议使用乐观锁解决这个问题。

举个例子:
假设order表里有个version字段,该字段只能单向自增(一般就是+1),SELECT的时候把version也查出来:

SELECT ..., version FROM order 
WHERE ...;

UPDATE order
SET ...,
version = version+1
WHERE version = 上一个SELECT语句带出来的version值

假设用户A和用户B在某时间段内先后或同时查出来order_id=1, version=1的订单,UPDATE的时候由于mysql行锁的存在,只会有一个用户UPDATE成功(1 rows affected),另一个用户则UPDATE失败(0 rows affected),然后可以根据UPDATE后返回的话行数判断用户是否抢单成功。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板