Redis

1.测试

package com.zx;

import org.junit.Test;
import redis.clients.jedis.Jedis;

import java.util.List;
import java.util.Set;

public class RedisTest {


    @Test
    public  void testContent(){
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        String ping= jedis.ping();
        System.out.println("ping = " + ping);
        Set<String> keys = jedis.keys("*");
        System.out.println("keys = " + keys);
        //判断某个key是否存在
        Boolean k1 = jedis.exists("k1");
        System.out.println("k1 = " + k1);
        //获取key类型
        String k7 = jedis.type("k7");
        System.out.println("k7 = " + k7);
        //k1的值
        String k11 = jedis.get("k1");
        System.out.println("k1的值 = " + k11);
        //k5的值list
        List<String> k51 = jedis.lrange("k5", 0, -1);
        for (String s :k51){
            System.out.println("s = " + s);
        }
        //获取set
        Set<String> k4 = jedis.smembers("k4");
        System.out.println("k4 = " + k4);

        //hash
        Set<String> k71 = jedis.hkeys("k7");
        System.out.println("k71 = " + k71);
        List<String> k72 = jedis.hvals("k7");
        System.out.println("k72 = " + k72);
        //zset
        Set<String> k8 = jedis.zrange("k8", 0, -1);
        System.out.println("k8 = " + k8);
    }
}
运行结果:
ping = PONG
keys = [k3, k4, k5, k7, k8, k1, k2]
k1 = true
k7 = hash
k1的值 = v2
s = v6
s = k6
s = v5
k4 = [v3, v1, v4, v2, v5]
k71 = [name, birth, age]
k72 = [zhangsan, 24, 2020-08-08]
k8 = [v3, v2, v1]

2.Redis手机验证码

Redis依赖

<dependencies>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
        <!--servlet-api-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

前端代码

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script  src="static/jquery/jquery-3.1.0.js" ></script>
<link href="static/bs/css/bootstrap.min.css" rel="stylesheet" />
<script  src="static/bs/js/bootstrap.min.js"   ></script>

</head>
<body>
   <div class="container">
		<div class="row">
		    <div id="alertdiv" class="col-md-12">
		          <form class="navbar-form navbar-left" role="search" id="codeform">
				  <div class="form-group">
				    <input type="text" class="form-control" placeholder="填写手机号" name="phone_no">
				    <button type="button" class="btn btn-default" id="sendCode">发送验证码</button><br>
				    <font id="countdown" color="red" ></font>
				    <br>
				    <input type="text" class="form-control" placeholder="填写验证码" name="verify_code">
				    <button type="button" class="btn btn-default" id="verifyCode">确定</button>
				    <font id="result" color="green" ></font><font id="error" color="red" ></font>
				    </div>
				    </form>
    </div>
   </div>
  </div>

</body>
<script type="text/javascript"> 
var t=120;//设定倒计时的时间 
var interval;
function refer(){  
    $("#countdown").text("请于"+t+"秒内填写验证码 "); // 显示倒计时 
    t--; // 计数器递减 
    if(t<=0){
    	clearInterval(interval);
    	$("#countdown").text("验证码已失效,请重新发送! ");
    }
} 

$(function(){
	$("#sendCode").click( function () {
	       
		   $.post("SendCodeServlet",$("#codeform").serialize(),function(data){
	    	 if(data=="true"){
	    		 t=120;
	    		 clearInterval(interval);
	    		 interval= setInterval("refer()",1000);//启动1秒定时  
	   		 }else if (data=="limit"){
	   			clearInterval(interval);
	   			$("#countdown").text("单日发送超过次数! ")
	   		 }
		  });   
    });
	
	$("#verifyCode").click( function () {
	    
		   $.post("CheckCodeServlet",$("#codeform").serialize(),function(data){
	    	 if(data=="true"){
	    		 $("#result").attr("color","green");
	    		 $("#result").text("验证成功");
	    		 clearInterval(interval);
	    		 $("#countdown").text("")
	   		 }else{
	    		 $("#result").attr("color","red");
	    		 $("#result").text("验证失败");
	   		 }
		  });   
    });
	
	
});
</script>
</html>

在这里插入图片描述

后端用servlet接收

1.接收手机号进行,生成验证码存入数据库120s,并进行每天3次判断

package com.atguigu.redis.servlet;

import javafx.scene.input.KeyCode;
import redis.clients.jedis.Jedis;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.Duration;
import java.time.LocalTime;
import java.util.Random;

//处理发送验证码的Servlet
@WebServlet("/SendCodeServlet")
public class SendCodeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取前端返回的值
        String phoneNo = request.getParameter("phone_no");
        System.out.println("phoneNo = " + phoneNo);
        //进行非空判断
        if (phoneNo==null|| "".equals(phoneNo)){
            return;
        }
        //手机号的次数
        String countKey=phoneNo+":count";
        System.out.println("countKey = " + countKey);
        //连接Redis
        Jedis jedis = new Jedis("127.0.0.1", 6379);

        String count = jedis.get(countKey);
        if (count==null){
            //调用计数方法
            long theLeftSeconds = getTheLeftSeconds();
            //写入数据库
            jedis.setex(countKey,(int)theLeftSeconds,"1");
        }else if("3".equals(count)){
            response.getWriter().write("limit");
            jedis.close();
        }else {
            //证明今天发送未超三次,将计数器加一
            jedis.incr(countKey);
        }
        System.out.println("count = " + count);
        String code = getCode(6);
        System.out.println("code = " + code);
        String keycode=phoneNo +":code";
        //写入数据库
        String setex = jedis.setex(keycode, 120, code);
        response.getWriter().write("true");
        jedis.close();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }

    // 随机生成验证码的方法
    private String getCode(int len) {
        String code = "";
        for (int i = 0; i < len; i++) {
            int rand = new Random().nextInt(10);
            code += rand;
        }
        return code;
    }

    //获取当天剩余秒数的方法
    private long getTheLeftSeconds(){
        //获取现在的时间
        LocalTime now = LocalTime.now();
        //获取当日23点59分59秒的时间
        LocalTime end = LocalTime.of(23, 59, 59);
        //获取end与now相差的秒数
        long millis = Duration.between(now, end).toMillis()/1000;
        return millis;
    }
}

2.接收数据库的验证码和前端输入的验证码经行判断

package com.atguigu.redis.servlet;

import redis.clients.jedis.Jedis;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

//处理验证验证码请求的Servlet
@WebServlet("/CheckCodeServlet")
public class CheckCodeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String verifyCode = request.getParameter("verify_code");
        String phoneNo = request.getParameter("phone_no");
        //非空判断
        if (verifyCode==null||"".equals(verifyCode)||phoneNo==null|| "".equals(phoneNo)){
            return;
        }
        String keycode=phoneNo +":code";
        //连接数据库
        Jedis jedis = new Jedis("127.0.0.10", 6379);
        //取值
        String riderskey = jedis.get(keycode);
        System.out.println("riderskey = " + riderskey);
        //和前端的值进行比较
        if (verifyCode.equals(riderskey)){
            jedis.del(keycode);
            response.getWriter().write("true");

        }
        jedis.close();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request,response);
    }
}

Redis事务

Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
Redis事务的主要作用就是串联多个命令防止别的命令插队

从输入Multi命令开始,输入的命令都会依次进入命令队列中,但不会执行,直到输入Exec后,Redis会将之前的命令队列中的命令依次执行。
组队的过程中可以通过discard来放弃组队

在这里插入图片描述

组队中某个命令出现了报告错误,执行时整个的所有队列都会被取消。

如果执行阶段某个命令报出了错误,则只有报错的命令不会被执行,而其他的命令都会执行,不会回滚。
在这里插入图片描述

悲观锁

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁

乐观锁

乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis就是利用这种check-and-set机制实现事务的。
WATCH key [key …]
在执行multi之前,先执行watch key1 [key2],可以监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

unwatch
取消 WATCH 命令对所有 key 的监视。
如果在执行 WATCH 命令之后,EXEC 命令或DISCARD 命令先被执行了的话,那么就不需要再执行UNWATCH 了。
4.6. Redis事务三特性

  1. 单独的隔离操作
    事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
  2. 没有隔离级别的概念
    队列中的命令没有提交之前都不会实际被执行,因为事务提交前任何指令都不会被实际执行
  3. 不保证原子性
    事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚

秒杀(方法)

//秒杀过程
	public static boolean doSecKill(String uid,String prodid) throws IOException {

		String kckey="sk:"+prodid+":qt";
		String userKey="sk:"+prodid+":usr";
		//Jedis jedis = new Jedis("127.0.0.1", 6379);
		//连接池对象
		JedisPool jedisPoolInstance = JedisPoolUtil.getJedisPoolInstance();
		//获取Jedis
		Jedis jedis = jedisPoolInstance.getResource();
		//添加乐观锁
		jedis.watch(kckey);

		String count = jedis.get(kckey);
		//判断
		if ("0".equals(count)){
			System.err.println("已经没有了");
			JedisPoolUtil.release(jedisPoolInstance,jedis);
			return false;
		}
//添加事务
		Transaction multi = jedis.multi();
		//组队
		multi.decr(kckey);
		//jedis.decr(kckey);

		//jedis.sadd(userKey,uid);
		multi.sadd(userKey,uid);

		//执行
		List<Object> exec = multi.exec();
		if (exec==null||exec.size()==0){
			//秒杀失败
			System.out.println("秒杀失败");
			//关闭资源
			JedisPoolUtil.release(jedisPoolInstance,jedis);
			jedis.close();
			return false;

		}


		return true;
	}

前后端交互

package com.atguigu.redis;

import redis.clients.jedis.Jedis;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Random;

/**
 * 秒杀案例
 */
@WebServlet("/doseckill")
public class SecKillServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//随机生成用户id
		String userid = new Random().nextInt(50000) +"" ;
		//获取商品id
		String prodid =request.getParameter("prodid");
		//秒杀
		//boolean isSuccess=SecKill_redis.doSecKill(userid,prodid);
		//解决库存问题
		boolean isSuccess = SecKill_redisByScript.doSecKill(userid, prodid);


		//给前端响应
		response.getWriter().print(isSuccess);
	}

}


Redis连接池

package com.atguigu.redis;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;ipackage com.atguigu.redis;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisPoolUtil {
	private static volatile JedisPool jedisPool = null;
//连接池
	private JedisPoolUtil() {
	}

	public static JedisPool getJedisPoolInstance() {
		if (null == jedisPool) {
			synchronized (JedisPoolUtil.class) {
				if (null == jedisPool) {
					JedisPoolConfig poolConfig = new JedisPoolConfig();
					poolConfig.setMaxTotal(200);
					poolConfig.setMaxIdle(32);
					poolConfig.setMaxWaitMillis(100*1000);
					poolConfig.setBlockWhenExhausted(true);
					poolConfig.setTestOnBorrow(true);  // ping  PONG
				 
					jedisPool = new JedisPool(poolConfig, "127.0.0.1", 6379, 60000 );
				}
			}
		}
		return jedisPool;
	}

	public static void release(JedisPool jedisPool, Jedis jedis) {
		if (null != jedis) {
			jedisPool.returnResource(jedis);
		}
	}

}

import redis.clients.jedis.JedisPooiesConfig;

public class JedisPoolUtil {
	private static volatile JedisPool jedisPool = null;
//连接池
	private JedisPoolUtil() {
	}

	public static JedisPool getJedisPoolInstance() {
		if (null == jedisPool) {
			synchronized (JedisPoolUtil.class) {
				if (null == jedisPool) {
					JedisPoolConfig poolConfig = new JedisPoolConfig();
					poolConfig.setMaxTotal(200);
					poolConfig.setMaxIdle(32);
					poolConfig.setMaxWaitMillis(100*1000);
					poolConfig.setBlockWhenExhausted(true);
					poolConfig.setTestOnBorrow(true);  // ping  PONG
				 
					jedisPool = new JedisPool(poolConfig, "127.0.0.1", 6379, 60000 );
				}
			}
		}
		return jedisPool;
	}

	public static void release(JedisPool jedisPool, Jedis jedis) {
		if (null != jedis) {
			jedisPool.returnResource(jedis);
		}
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想要入门的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值