Skip to content

Commit

Permalink
lua+redis
Browse files Browse the repository at this point in the history
  • Loading branch information
qiurunze committed Feb 21, 2019
1 parent 42d4bb2 commit 0f92dcc
Show file tree
Hide file tree
Showing 43 changed files with 1,518 additions and 114 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
| 028 |项目进行dubbo + zk 改造 (已完成dubbo嵌入--springboot 与dubbo结合xml版本)?|[解决思路](/docs/code-solve.md) |
| 029 |dubbo客户端 dubbo-admin管理平台 搭建安装|[解决思路](/docs/dubbo-admin.md) |
| 030 |如何利用dubbo 的mock 来进行服务降级本地伪装 ?? (有更好的方式进群@我)|[解决思路](/docs/dubbo-zk.md) |
| 027 |*** 如何利用lua + redis 取代 nigix + lua 脚本进行分布式限流 ? *** |[解决思路](/docs/redis-good.md) |
| 027 |*** 如何利用lua + redis 取代 nigix + lua 脚本进行分布式限流 (请看miaosha-2version) *** |[解决思路](/docs/redis-good.md) |


#### [分布式系统发展历程(已更新)](/docs/fenbushi.md)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public class AbstractResult {
private int code;
private String message;

AbstractResult() {}
protected AbstractResult(ResultStatus status, String message) {
this.code = status.getCode();
this.status = status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public class ResultGeekQ<T> extends AbstractResult implements Serializable {
private T data;
private Integer count;

protected ResultGeekQ() {
}
protected ResultGeekQ(ResultStatus status, String message) {
super(status, message);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.geekq.miasha.vo;

import com.geekq.api.entity.GoodsVoOrder;
import com.geekq.miasha.entity.MiaoshaUser;
import lombok.AllArgsConstructor;
import lombok.Getter;
Expand All @@ -14,7 +15,7 @@
public class GoodsDetailVo {
private int miaoshaStatus = 0;
private int remainSeconds = 0;
private GoodsVo goods ;
private GoodsVoOrder goods ;
private MiaoshaUser user;

}
7 changes: 7 additions & 0 deletions miaosha-2version/miaosha-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,12 @@


</build>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ public interface MiaoShaUserMapper {

public void insertMiaoShaUser(MiaoshaUser miaoshaUser);

public int getCountByUserName(@Param("userName")String userName , @Param("userType")int userType);
public int getCountByUserName(@Param("userName") String userName, @Param("userType") int userType);

}
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
package com.geekq.miaosha.rabbitmq;

import com.geekq.api.entity.GoodsVoOrder;
import com.geekq.api.utils.AbstractResultOrder;
import com.geekq.api.utils.ResultGeekQOrder;
import com.geekq.miaosha.redis.RedisService;
import com.geekq.miaosha.service.GoodsService;
import com.geekq.miaosha.service.MiaoShaMessageService;
import com.geekq.miaosha.service.MiaoshaService;
import com.geekq.miaosha.service.OrderService;
import com.geekq.miasha.entity.MiaoshaOrder;
import com.geekq.miasha.entity.MiaoshaUser;
import com.geekq.miasha.vo.GoodsVo;
import com.geekq.miasha.vo.MiaoShaMessageVo;
import com.rabbitmq.client.Channel;
import com.geekq.miasha.enums.enums.ResultStatus;
import com.geekq.miasha.exception.GlobleException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;

@Service
public class MQReceiver {

Expand All @@ -36,6 +34,9 @@ public class MQReceiver {
@Autowired
MiaoshaService miaoshaService;

@Autowired
private com.geekq.api.service.GoodsService goodsServiceRpc;

// @Autowired
// MiaoShaMessageService messageService ;

Expand All @@ -46,7 +47,13 @@ public void receive(String message) {
MiaoshaUser user = mm.getUser();
long goodsId = mm.getGoodsId();

GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
// GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
ResultGeekQOrder<GoodsVoOrder> goodsVoOrderResultGeekQOrder = goodsServiceRpc.getGoodsVoByGoodsId(goodsId);
if(!AbstractResultOrder.isSuccess(goodsVoOrderResultGeekQOrder)){
throw new GlobleException(ResultStatus.SESSION_ERROR);
}

GoodsVoOrder goods= goodsVoOrderResultGeekQOrder.getData();
int stock = goods.getStockCount();
if(stock <= 0) {
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.geekq.miaosha.redis.redismanager;

import redis.clients.jedis.Jedis;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class RedisLimitRateWithLUA {

public static void main(String[] args) {
final CountDownLatch latch = new CountDownLatch(1);

for (int i = 0; i < 20; i++) {
new Thread(new Runnable() {
public void run() {
try {
latch.await();
System.out.println("请求是否被执行:"+accquire());
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();

}

latch.countDown();
}

public static boolean accquire() throws IOException, URISyntaxException {
Jedis jedis = new Jedis("39.107.245.253");

String lua =
"local key = KEYS[1] " +
" local limit = tonumber(ARGV[1]) " +
" local current = tonumber(redis.call('get', key) or '0')" +
" if current + 1 > limit " +
" then return 0 " +
" else "+
" redis.call('INCRBY', key,'1')" +
" redis.call('expire', key,'2') " +
" end return 1 ";

String key = "ip:" + System.currentTimeMillis()/1000; // 当前秒
String limit = "3"; // 最大限制
List<String> keys = new ArrayList<String>();
keys.add(key);
List<String> args = new ArrayList<String>();
args.add(limit);
jedis.auth("youxin11");
String luaScript = jedis.scriptLoad(lua);
Long result = (Long)jedis.evalsha(luaScript, keys, args);
return result == 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import java.util.ArrayList;
import java.util.List;

import static redis.clients.jedis.Protocol.Command.INCRBY;

/**
* lua脚本使用
*/
Expand Down Expand Up @@ -92,4 +94,37 @@ public static void vistorCount(String key) {
logger.error("统计访问次数失败!!!",e);
}
}


public static void currentlimitMinute() {

Jedis jedis = null;
try {
jedis = RedisManager.getJedis();
} catch (Exception e) {
e.printStackTrace();
}
String lua =
"local key = KEYS[1] " +
"local limit = tonumber(ARGV[1]) " +
"local current = tonumber(redis.call('get', key) or '0') " +
"if current + 1 > limit then return 0 " +
"else redis.call('INCRBY', key,'1')" +
" redis.call('expire', key,'2') " +
"end return 1";

List<String> keys = new ArrayList<String>();
keys.add("ip:limit:127.0.0.1");
List<String> argves = new ArrayList<String>();
argves.add("6000");
argves.add("5");
jedis.auth("xxxx");

// Object evalSha = jedis.evalsha(lua);
String luaScript = jedis.scriptLoad(lua);
System.out.println(luaScript);
Object object = jedis.evalsha(luaScript, keys, argves);
System.out.println(object);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
local key = KEYS[1] --限流KEY(一秒一个)
local limit = tonumber(ARGV[1]) --限流大小
local current = tonumber(redis.call('get', key) or "0")
if current + 1 > limit then --如果超出限流大小
return 0
else --请求数+1,并设置2秒过期
redis.call("INCRBY", key,"1")
redis.call("expire", key,"2")
end
return 1



-- ip限流


local key = "rate.limit:" .. KEYS[1]
local limit = tonumber(ARGV[1])
local expire_time = ARGV[2]

local is_exists = redis.call("EXISTS", key)
if is_exists == 1 then
if redis.call("INCR", key) > limit then
return 0
else
return 1
end
else
redis.call("SET", key, 1)
redis.call("EXPIRE", key, expire_time)
return 1
end
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.geekq.miaosha.service;

import com.alibaba.dubbo.config.annotation.Reference;
import com.geekq.api.entity.GoodsVoOrder;
import com.geekq.miaosha.redis.MiaoshaKey;
import com.geekq.miaosha.redis.RedisService;
import com.geekq.miasha.entity.MiaoshaOrder;
Expand Down Expand Up @@ -29,10 +31,14 @@ public class MiaoshaService {
@Autowired
RedisService redisService;

@Reference(version = "${demo.service.version}",retries = 3,timeout = 6000)
private com.geekq.api.service.GoodsService goodsServiceRpc;

@Transactional
public OrderInfo miaosha(MiaoshaUser user, GoodsVo goods) {
public OrderInfo miaosha(MiaoshaUser user, GoodsVoOrder goods) {
//减库存 下订单 写入秒杀订单
boolean success = goodsService.reduceStock(goods);
// boolean success = goodsService.reduceStock(goods);
boolean success =goodsServiceRpc.reduceStock(goods);
if(success){
return orderService.createOrder(user,goods) ;
}else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.geekq.miaosha.service;

import com.geekq.api.entity.GoodsVoOrder;
import com.geekq.miaosha.mapper.OrderMapper;
import com.geekq.miaosha.redis.OrderKey;
import com.geekq.miaosha.redis.RedisService;
Expand Down Expand Up @@ -37,7 +38,7 @@ public OrderInfo getOrderById(long orderId) {
}

@Transactional
public OrderInfo createOrder(MiaoshaUser user, GoodsVo goods) {
public OrderInfo createOrder(MiaoshaUser user, GoodsVoOrder goods) {
OrderInfo orderInfo = new OrderInfo();
orderInfo.setCreateDate(new Date());
orderInfo.setDeliveryAddrId(0L);
Expand Down
10 changes: 10 additions & 0 deletions miaosha-2version/miaosha-service/src/main/resources/limit.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
local key = KEYS[1] --限流KEY(一秒一个)
local limit = tonumber(ARGV[1]) --限流大小
local current = tonumber(redis.call('get', key) or "0")
if current + 1 > limit then --如果超出限流大小
return 0
else --请求数+1,并设置2秒过期
redis.call("INCRBY", key,"1")
redis.call("expire", key,"2")
end
return 1
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package com.geekq.miaosha;

import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;

@EnableDubbo
@ImportResource(value={"classpath:consumer.xml"})
@SpringBootApplication
@MapperScan("com.geekq.miaosha.mapper")
public class GeekQMainApplication {

public static void main(String[] args) throws Exception {
// RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
// Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://localhost:2181"));
// registry.register(URL.valueOf("override://0.0.0.0/com.geekq.api.service.GoodsService?category=configurators&dynamic=false&application=dubbo-consumer2.0&mock=fail:return+444"));
SpringApplication.run(GeekQMainApplication.class, args);
}

Expand Down
Loading

0 comments on commit 0f92dcc

Please sign in to comment.