博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
redis 令牌桶算法—Lua
阅读量:4037 次
发布时间:2019-05-24

本文共 2490 字,大约阅读时间需要 8 分钟。

令牌桶算法

场景:秒杀(也可以用于平滑限流某个接口请求)


import java.io.IOException;import java.nio.charset.Charset;import org.springframework.core.io.ClassPathResource;import com.google.common.io.Files;import redis.clients.jedis.Jedis;/*** *@author dzb *@date 2019/11/3 22:09 *@Description:  令牌桶 * */public class JedisLuaTokenTimeLimiter {	/**执行脚本**/	private String luaScript;	/**值**/	private String key;	/**限流次数**/	private String limit;	/**时间**/	private String expire;	public JedisLuaTokenTimeLimiter(String key, String limit, String expire, String scriptFile) {		super();		this.key = key;		this.limit = limit;		this.expire = expire;		try {			luaScript = Files.asCharSource(new ClassPathResource(scriptFile).getFile(), Charset.defaultCharset())					.read();		} catch (IOException e) {			e.printStackTrace();		}	}	/***	 * 释放获取	 * */	public boolean acquire() {		Jedis jedis = new Jedis("localhost", 6379);		return (Long) jedis.eval(luaScript, 1, key, limit, expire) == 1L;	}}
--令牌秒杀 Lua脚本  tokenTimeLimiter.lualocal key = KEYS[1] 			--限流KEY(一秒一个)local limit = tonumber(ARGV[1]) --限流大小local exprie = ARGV[2] 			--过期时间-- 获取当前计数值local current = tonumber(redis.call('get', key) or "0")if current + 1 > limit then --如果超出限流大小    return 0else	current = tonumber(redis.call("INCRBY", key, "1")) --请求数+1	if current == 1 then  --第一次访问需要设置过期时间    	redis.call("expire", key,exprie) --设置过期时间    endendreturn 1  --返回1代表不限流
Controller层//模拟秒杀场景	JedisLuaTokenTimeLimiter jtwlm = new JedisLuaTokenTimeLimiter("商品A", "5", "1", "tokenTimeLimiter.lua");	public String doQuery(String name) throws Exception {		// 从redis 上获得 自增后的值		if (!jtwlm.acquire()) {			return System.currentTimeMillis() / 1000 + "秒杀结束,谢谢参与!";		}		return System.currentTimeMillis() / 1000 + "恭喜,秒杀成功!";	}

测试代码

//模拟场景并发	 @Test	public void tokenTimeLimiter() throws Exception {		CountDownLatch cdl = new CountDownLatch(10);		CyclicBarrier cyb = new CyclicBarrier(10);		for (int i = 0; i < 10; i++) {			new Thread(() -> {				try {					cyb.await();				} catch (InterruptedException | BrokenBarrierException e) {					e.printStackTrace();				}				try {					System.out.println(Thread.currentThread().getName() + " " + orderc.doQuery("商品A"));				} catch (Exception e) {					e.printStackTrace();				}				cdl.countDown();			}).start();		}		try {			cdl.await();		} catch (InterruptedException e) {			e.printStackTrace();		}		TimeUnit.SECONDS.sleep(1);		System.out.println(Thread.currentThread().getName() + " " + orderc.doQuery("商品A"));	}

结果:

注:本人只是简单的模拟了分布式环境并发的场景,其细节还有很多就没有过多给出。

转载地址:http://nujdi.baihongyu.com/

你可能感兴趣的文章
Phone双模修改涉及文件列表
查看>>
android UI小知识点
查看>>
Android之TelephonyManager类的方法详解
查看>>
android raw读取超过1M文件的方法
查看>>
ubuntu下SVN服务器安装配置
查看>>
MPMoviePlayerViewController和MPMoviePlayerController的使用
查看>>
CocoaPods实践之制作篇
查看>>
[Mac]Mac 操作系统 常见技巧
查看>>
苹果Swift编程语言入门教程【中文版】
查看>>
捕鱼忍者(ninja fishing)之游戏指南+游戏攻略+游戏体验
查看>>
iphone开发基础之objective-c学习
查看>>
iphone开发之SDK研究(待续)
查看>>
计算机网络复习要点
查看>>
Variable property attributes or Modifiers in iOS
查看>>
NSNotificationCenter 用法总结
查看>>
C primer plus 基础总结(一)
查看>>
剑指offer算法题分析与整理(一)
查看>>
剑指offer算法题分析与整理(三)
查看>>
Ubuntu 13.10使用fcitx输入法
查看>>
pidgin-lwqq 安装
查看>>