使用redis模拟抢购商品
1、在pom.xm文件中引入依赖
<!-- redis包--> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>2.1.5.RELEASE</version> </dependency>
2、添加配置文件dev.properties
redis.host=127.0.0.1
redis.port=6379
redis.password=123456
redis.database=2
redis.timeout=120000
3、添加redis.xml文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:properties/dev.properties</value> <value>file:/home/wang/properties/wang-test.properties</value> <value>file:/home/wang/properties/wang-stage.properties</value> <value>file:/home/wang/properties/wang-deploy.properties</value> </list> </property> <property name="ignoreResourceNotFound" value="true" /> </bean> <!-- 连接池配置 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <!-- 最大连接数 --> <property name="maxTotal" value="30" /> <!-- 最大空闲连接数 --> <property name="maxIdle" value="10" /> <!-- 每次释放连接的最大数目 --> <property name="numTestsPerEvictionRun" value="1024" /> <!-- 释放连接的扫描间隔(毫秒) --> <property name="timeBetweenEvictionRunsMillis" value="30000" /> <!-- 连接最小空闲时间 --> <property name="minEvictableIdleTimeMillis" value="1800000" /> <!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 --> <property name="softMinEvictableIdleTimeMillis" value="10000" /> <!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 --> <property name="maxWaitMillis" value="1500" /> <!-- 在获取连接的时候检查有效性, 默认false --> <property name="testOnBorrow" value="true" /> <!-- 在空闲时检查有效性, 默认false --> <property name="testWhileIdle" value="true" /> <!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true --> <property name="blockWhenExhausted" value="false" /> </bean> <!-- jedis客户端单机版 --> <bean id="redisClient" class="redis.clients.jedis.JedisPool"> <constructor-arg name="host" value="${redis.host}"/> <constructor-arg name="port" value="${redis.port}"/> <constructor-arg name="password" value="${redis.password}"/> <constructor-arg name="database" value="${redis.database}"/> <constructor-arg name="timeout" value="${redis.timeout}"/> <constructor-arg name="poolConfig" ref="jedisPoolConfig"/> </bean> <bean id="jedisClient" class="com.base.wang.service.impl.JedisClientSingle"/> <!-- jedis集群版配置 --> <!-- <bean id="redisClient" class="redis.clients.jedis.JedisCluster"> <constructor-arg name="nodes"> <set> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.25.153"></constructor-arg> <constructor-arg name="port" value="7001"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.25.153"></constructor-arg> <constructor-arg name="port" value="7002"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.25.153"></constructor-arg> <constructor-arg name="port" value="7003"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.25.153"></constructor-arg> <constructor-arg name="port" value="7004"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.25.153"></constructor-arg> <constructor-arg name="port" value="7005"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.25.153"></constructor-arg> <constructor-arg name="port" value="7006"></constructor-arg> </bean> </set> </constructor-arg> <constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg> </bean> <bean id="jedisClientCluster" class="com.taotao.rest.dao.impl.JedisClientCluster"></bean> --> </beans>
4、JedisClient接口类
package com.base.wang.service; import java.util.List; import java.util.Map; import java.util.Set; /** * Created by wxb on 2019/3/5. */ public interface JedisClient { //---》》》》Hash String get(String key);//读取数据 String set(String key,String value);//向redis中写入数据 long incr(String key); /** * 确认一个key是否存在 */ Boolean exists(String key); /** *删除一个key */ long del(String key); /** *删除多个key */ long del(String... key);//删除数据 /** * 返回值的类型 */ String type(String key); /** * 设定一个key的活动时间(s) */ long expire(String key,int second);//设置缓存生存时间 /** * 获得一个key的活动时间 */ long ttl(String key); /** * 将当前数据库中的key转移到有dbindex索引的数据库 */ Long move(String key, int dbindex); //---》》》》Hash /** *向名称为key的hash中添加元素field<—>value */ long hset(String hkey,String key,String value); /** * 返回名称为key的hash中field对应的value */ String hget(String hkey,String key); /** *返回名称为key的hash中field i对应的value */ List<String> hmget(String hkey, String... field); /** *向名称为key的hash中添加元素field i<—>value i */ String hmset(String hkey, Map<String, String> map); /** * 名称为key的hash中是否存在键为field的域 */ Boolean hexists(String hkey, String field); /** * 删除名称为key的hash中键为field的域 */ Long hdel(String hkey, String... field); /** * 返回名称为key的hash中元素个数 */ Long hlen(String hkey); /** * 返回名称为key的hash中所有键 */ Set<String> hkeys(String hkey); /** * 返回名称为key的hash中所有键对应的value */ List<String> hvals(String hkey); /** * 返回名称为key的hash中所有的键(field)及其对应的value */ Map<String, String> hgetAll(String hkey); //---》》》》List /** * 在名称为key的list尾添加一个值为value的元素 */ Long rpush(String key, String... strings); /** * 在名称为key的list头添加一个值为value的 元素 */ Long lpush(String key, String... strings); /** * 返回名称为key的list的长度 */ Long llen(String key); /** * 返回名称为key的list中start至end之间的元素(下标从0开始,下同) */ List<String> lrange(String key, long start, long end); /** * 截取名称为key的list,保留start至end之间的元素 */ String ltrim(String key, long start, long end); /** * 返回名称为key的list中index位置的元素 */ String lindex(String key, long index); /*** * 给名称为key的list中index位置的元素赋值为value */ String lset(String key, long index, String value); /** * 删除count个名称为key的list中值为value的元素。count为0,删除所有值为value的元素,count>0 从头至尾删除count个值为value的元素,count<0从尾到头删除|count|个值为value的元素。 */ Long lrem(String key, long count, String value); /** * 返回并删除名称为key的list中的首元素 */ String lpop(String key); /** * 返回并删除名称为key的list中的尾元素 */ String rpop(String key); //---》》》》Set /** * 向名称为key的set中添加元素member */ Long sadd(String key, String... member); /** * 删除名称为key的set中的元素member */ Long srem(String key, String... member); /** * 随机返回并删除名称为key的set中一个元素 */ String spop(String key); /** * 返回名称为key的set的基数 */ Long scard(String key); /** * 测试member是否是名称为key的set的元素 */ Boolean sismember(String key, String member); /** * 随机返回名称为key的set的一个元素 */ String srandmember(String key); }
5、JedisClientSingle 单机 实现类
package com.base.wang.service.impl; import com.base.wang.service.JedisClient; import org.springframework.beans.factory.annotation.Autowired; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import java.util.List; import java.util.Map; import java.util.Set; public class JedisClientSingle implements JedisClient { @Autowired private JedisPool jedisPool; @Override public String get(String key) { Jedis jedis = jedisPool.getResource(); String string = jedis.get(key); jedis.close(); return string; } @Override public String set(String key, String value) { Jedis jedis = jedisPool.getResource(); String string = jedis.set(key, value); jedis.close(); return string; } @Override public long incr(String key) { Jedis jedis = jedisPool.getResource(); Long result = jedis.incr(key); jedis.close(); return result; } @Override public Boolean exists(String key) { Jedis jedis = jedisPool.getResource(); Boolean result = jedis.exists(key); jedis.close(); return result; } @Override public long del(String key) { Jedis jedis = jedisPool.getResource(); Long result = jedis.del(key); jedis.close(); return result; } @Override public long del(String... key) { Jedis jedis = jedisPool.getResource(); Long result = jedis.del(key); jedis.close(); return result; } @Override public String type(String key) { Jedis jedis = jedisPool.getResource(); String result = jedis.type(key); jedis.close(); return result; } @Override public long expire(String key, int second) { Jedis jedis = jedisPool.getResource(); Long result = jedis.expire(key,second); jedis.close(); return result; } @Override public long ttl(String key) { Jedis jedis = jedisPool.getResource(); Long result = jedis.ttl(key); jedis.close(); return result; } @Override public Long move(String key, int dbindex) { Jedis jedis = jedisPool.getResource(); Long result = jedis.move(key,dbindex); jedis.close(); return result; } //---》》》》List @Override public long hset(String hkey, String key, String value) { Jedis jedis = jedisPool.getResource(); Long result = jedis.hset(hkey, key, value); jedis.close(); return result; } @Override public String hget(String hkey, String key) { Jedis jedis = jedisPool.getResource(); String result = jedis.hget(hkey, key); jedis.close(); return result; } @Override public List<String> hmget(String hkey, String... field) { Jedis jedis = jedisPool.getResource(); List<String> result = jedis.hmget(hkey, field); jedis.close(); return result; } @Override public String hmset(String hkey, Map<String, String> map) { Jedis jedis = jedisPool.getResource(); String result = jedis.hmset(hkey, map); jedis.close(); return result; } @Override public Boolean hexists(String hkey, String field) { Jedis jedis = jedisPool.getResource(); Boolean result = jedis.hexists(hkey, field); jedis.close(); return result; } @Override public Long hdel(String hkey, String... field) { Jedis jedis = jedisPool.getResource(); Long result = jedis.hdel(hkey, field); jedis.close(); return result; } @Override public Long hlen(String hkey) { Jedis jedis = jedisPool.getResource(); Long result = jedis.hlen(hkey); jedis.close(); return result; } @Override public Set<String> hkeys(String hkey) { Jedis jedis = jedisPool.getResource(); Set<String> result = jedis.hkeys(hkey); jedis.close(); return result; } @Override public List<String> hvals(String hkey) { Jedis jedis = jedisPool.getResource(); List<String> result = jedis.hvals(hkey); jedis.close(); return result; } @Override public Map<String, String> hgetAll(String hkey) { Jedis jedis = jedisPool.getResource(); Map<String, String> result = jedis.hgetAll(hkey); jedis.close(); return result; } //---》》》》List @Override public Long rpush(String key, String... strings) { Jedis jedis = jedisPool.getResource(); Long result=jedis.rpush(key,strings); jedis.close(); return result; } @Override public Long lpush(String key, String... strings) { Jedis jedis = jedisPool.getResource(); Long result=jedis.lpush(key,strings); jedis.close(); return result; } @Override public Long llen(String key) { Jedis jedis = jedisPool.getResource(); Long result=jedis.llen(key); jedis.close(); return result; } @Override public List<String> lrange(String key, long start, long end) { Jedis jedis = jedisPool.getResource(); List<String> list=jedis.lrange(key,start,end); jedis.close(); return list; } @Override public String ltrim(String key, long start, long end) { Jedis jedis = jedisPool.getResource(); String result=jedis.ltrim(key,start,end); jedis.close(); return result; } @Override public String lindex(String key, long index) { Jedis jedis = jedisPool.getResource(); String result=jedis.lindex(key,index); jedis.close(); return result; } @Override public String lset(String key, long index, String value) { Jedis jedis = jedisPool.getResource(); String result=jedis.lset(key,index,value); jedis.close(); return result; } @Override public Long lrem(String key, long count, String value) { Jedis jedis = jedisPool.getResource(); Long result=jedis.lrem(key,count,value); jedis.close(); return result; } @Override public String lpop(String key) { Jedis jedis = jedisPool.getResource(); String result=jedis.lpop(key); jedis.close(); return result; } @Override public String rpop(String key) { Jedis jedis = jedisPool.getResource(); String result=jedis.rpop(key); jedis.close(); return result; } //---》》》》Set @Override public Long sadd(String key, String... member) { Jedis jedis = jedisPool.getResource(); Long result=jedis.sadd(key,member); jedis.close(); return result; } @Override public Long srem(String key, String... member) { Jedis jedis = jedisPool.getResource(); Long result=jedis.srem(key,member); jedis.close(); return result; } @Override public String spop(String key) { Jedis jedis = jedisPool.getResource(); String result=jedis.spop(key); jedis.close(); return result; } @Override public Long scard(String key) { Jedis jedis = jedisPool.getResource(); Long result=jedis.scard(key); jedis.close(); return result; } @Override public Boolean sismember(String key, String member) { Jedis jedis = jedisPool.getResource(); Boolean result=jedis.sismember(key,member); jedis.close(); return result; } @Override public String srandmember(String key) { Jedis jedis = jedisPool.getResource(); String result=jedis.srandmember(key); jedis.close(); return result; } }
6、JedisClientCluster 集群实现类
package com.base.wang.service.impl; import com.base.wang.service.JedisClient; import org.springframework.beans.factory.annotation.Autowired; import redis.clients.jedis.JedisCluster; import java.util.List; import java.util.Map; import java.util.Set; public class JedisClientCluster implements JedisClient { @Autowired private JedisCluster jedisCluster; @Override public String get(String key) { return jedisCluster.get(key); } @Override public String set(String key, String value) { return jedisCluster.set(key, value); } @Override public String hget(String hkey, String key) { return jedisCluster.hget(hkey, key); } @Override public List<String> hmget(String hkey, String... field) { return jedisCluster.hmget(hkey, field); } @Override public String hmset(String hkey, Map<String, String> map) { return jedisCluster.hmset(hkey, map); } @Override public Boolean hexists(String hkey, String field) { return jedisCluster.hexists(hkey, field); } @Override public Long hdel(String hkey, String... field) { return jedisCluster.hdel(hkey, field); } @Override public Long hlen(String hkey) { return jedisCluster.hlen(hkey); } @Override public Set<String> hkeys(String hkey) { return jedisCluster.hkeys(hkey); } @Override public List<String> hvals(String hkey) { return jedisCluster.hvals(hkey); } @Override public Map<String, String> hgetAll(String hkey) { return jedisCluster.hgetAll(hkey); } @Override public long hset(String hkey, String key, String value) { return jedisCluster.hset(hkey, key, value); } @Override public long incr(String key) { return jedisCluster.incr(key); } @Override public Boolean exists(String key) { return jedisCluster.exists(key); } @Override public long expire(String key, int second) { return jedisCluster.expire(key, second); } @Override public long ttl(String key) { return jedisCluster.ttl(key); } @Override public Long move(String key, int dbindex) { return jedisCluster.move(key,dbindex); } @Override public long del(String key) { return jedisCluster.del(key); } @Override public long del(String... key) { return 0; } @Override public String type(String key) { return jedisCluster.type(key); } @Override public Long rpush(String key, String... strings) { return jedisCluster.rpush(key,strings); } @Override public Long lpush(String key, String... strings) { return jedisCluster.rpush(key,strings); } @Override public Long llen(String key) { return jedisCluster.llen(key); } @Override public List<String> lrange(String key, long start, long end) { return jedisCluster.lrange(key,start,end); } @Override public String ltrim(String key, long start, long end) { return jedisCluster.ltrim(key,start,end); } @Override public String lindex(String key, long index) { return jedisCluster.lindex(key,index); } @Override public String lset(String key, long index, String value) { return jedisCluster.lset(key,index,value); } @Override public Long lrem(String key, long count, String value) { return jedisCluster.lrem(key,count,value); } @Override public String lpop(String key) { return jedisCluster.lpop(key); } @Override public String rpop(String key) { return jedisCluster.rpop(key); } //---》》》》Set @Override public Long sadd(String key, String... member) { return jedisCluster.sadd(key,member); } @Override public Long srem(String key, String... member) { return jedisCluster.srem(key,member); } @Override public String spop(String key) { return jedisCluster.spop(key); } @Override public Long scard(String key) { return jedisCluster.scard(key); } @Override public Boolean sismember(String key, String member) { return jedisCluster.sismember(key,member); } @Override public String srandmember(String key) { return jedisCluster.srandmember(key); } }
7、controller类
package com.base.wang.controller; import com.base.wang.entity.BasTest; import com.base.wang.service.RedisService; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; /** * Created by wxb on 2019/3/5. */ @RestController @RequestMapping("/redis") public class RedisController { private Logger log = Logger.getLogger(this.getClass()); @Autowired private RedisService redisService; @ResponseBody @RequestMapping("/findById") public Object findById(Integer id){ BasTest test = redisService.findById(id); return test; } /** * 初始化商品 * @return */ @ResponseBody @RequestMapping("/initStores") public Object initStores(){ return redisService.initStores(); } /** * 抢购商品 * @return */ @ResponseBody @RequestMapping("/rushToBuy") public Object rushToBuy(){ return redisService.rushToBuy(); } }
8、抢购商品实现
package com.base.wang.service.impl; import com.base.wang.common.PageReturn; import com.base.wang.entity.BasTest; import com.base.wang.mapper.BasTestMapper; import com.base.wang.service.JedisClient; import com.base.wang.service.RedisService; import com.base.wang.util.JsonUtil; import com.base.wang.util.StringUtil; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.UUID; /** * Created by wxb on 2019/3/5. */ @Service("redisService") public class RedisServiceImpl extends BaseServiceImpl<BasTest> implements RedisService { private Logger log = Logger.getLogger(this.getClass()); static final int stores = 1000;//库存量 static final String storesName = "stores";//抢购商品存放仓库名称 static final String storesCountKey = "storesCountKey";//记录以往仓库中存放商品的数量的KEY static final String setSuccessName = "setSuccessName";//记录抢购成功用户的set集合KEY static final String setFailName = "setFailName";//记录抢购失败用户的set集合KEY @Autowired private BasTestMapper testMapper; @Autowired private JedisClient jedisClient; @Override public BasTest findById(Integer id) { String dataStr=jedisClient.hget("wangxiaobing",id+""); if(StringUtil.isEmpty(dataStr)){ System.out.println("--->>>>1111"); BasTest test= testMapper.findById(id); if(test==null)return null; jedisClient.hset("wangxiaobing",id+"", JsonUtil.toJson(test)); return test; }else { System.out.println("--->>>>22222"); BasTest test= JsonUtil.json2Object(dataStr,BasTest.class); return test; } } @Override public Object initStores() { ////初始化 jedisClient.del(storesName, setSuccessName, setFailName);//删除仓库,删除抢购成功队列,删除抢购失败队列 jedisClient.set(storesCountKey, stores + ""); for (int i = 1; i <= stores; i++) { String storeProp = i + ":" + UUID.randomUUID().toString();//模拟 序号:ID jedisClient.rpush(storesName, storeProp); } return PageReturn.success(); } @Override public Object rushToBuy(){ String userifo = UUID.randomUUID().toString(); //redis list取值 String ls = jedisClient.lpop(storesName); //取值成功,说明拿到了商品,即抢购成功 if (ls != null) { String[] er = ls.split(":"); int num = Integer.valueOf(er[0]);//商品序号 String ID = er[1];//商品ID /* 抢购成功业务逻辑 */ jedisClient.sadd(setSuccessName, userifo); System.out.println("用户:" + userifo + "抢购成功,当前抢购成功人数:" + num + "------抢购成功商品ID:" + ID); try { Thread.sleep(900);//模拟业务执行时间 } catch (InterruptedException e) { e.printStackTrace(); } return PageReturn.success("用户:" + userifo + "抢购成功,当前抢购成功人数:" + num + "------抢购成功商品ID:" + ID); } else { jedisClient.sadd(setFailName, userifo); System.out.println("用户:" + userifo + "抢购失败,库存以空"); try { Thread.sleep(400);//模拟业务执行时间 } catch (InterruptedException e) { e.printStackTrace(); } return PageReturn.fail("用户:" + userifo + "抢购失败,库存以空"); } } }
项目代码见:
https://github.com/wxb100200/wang-base.git

浙公网安备 33010602011771号