Heim > Fragen und Antworten > Hauptteil
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; } }
三叔2016-11-11 10:03:00
没太看懂你的代码表达的意思,感觉跟你的描述不太相符。
用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后返回的话行数判断用户是否抢单成功。