Redis(Idea学习)

先添加Jedis依赖

测试是否连接成功

    public static void main(String[] args) {
        //1、创建Jedis对象
        Jedis jedis=new Jedis("192.168.111.130",6379);//前面个是连接的主机ip,后面个是redis的端口号
        //2、测试
        String ping=jedis.ping();
        //成功返回PONG
        System.out.println(ping);
    }

如果未成功之前写的配置文件有讲,修改即可。

使用示例

    /**
     * 操作 String
     */
    @Test
    public void testString(){
        Jedis jedis=new Jedis("192.168.111.130",6379);//前面个是连接的主机ip,后面个是redis的端口号
        jedis.set("name","lisi");//添加
        System.out.println(jedis.get("name"));//取值
        jedis.mset("school","cqupt","position","nanshan");//一次添加多个
        System.out.println("======================================");
        Set<String> set=jedis.keys("*");//查看所有的key
        for (String x:set)
            System.out.println(x);
    }
    /**
     * 操作 list
     */
    @Test
    public void testList(){
        Jedis jedis=new Jedis("192.168.111.130",6379);//前面个是连接的主机ip,后面个是redis的端口号
        jedis.lpush("name","zhangsan","lisi","wangwu");//list添加
        System.out.println("======================================");
        List<String> set=jedis.lrange("name",0,-1);//取出name中所value
        for (String key:set)
        System.out.println(key);
    }
    /**
     * 操作 Set
     */
    @Test
    public void testSet(){
        Jedis jedis=new Jedis("192.168.111.130",6379);//前面个是连接的主机ip,后面个是redis的端口号
        jedis.sadd("school","qupt","cqust");
        System.out.println("======================================");
        Set<String> set=jedis.smembers("school");
        for (String key:set)
            System.out.println(key);
    }
    /**
     * 操作 Hash
     */
    @Test
    public void testHash(){
        Jedis jedis=new Jedis("192.168.111.130",6379);//前面个是连接的主机ip,后面个是redis的端口号
        Map<String,String> map=new HashMap<String, String>();
        map.put("java","200");
        map.put("c++","250");
        jedis.hset("programmer",map);

        System.out.println("======================================");
        String set=jedis.hget("programmer","c++");
        System.out.println(set);
    }
    /**
     * 操作 Zset
     */
    @Test
    public void testZset(){
        Jedis jedis=new Jedis("192.168.111.130",6379);//前面个是连接的主机ip,后面个是redis的端口号
        jedis.zadd("brand",2,"绿豆");
        jedis.zadd("brand",5,"可爱多");
        System.out.println("======================================");
        Set<String> set=jedis.zrange("brand",0,1);
        for (String key:set)
            System.out.println(key);
    }

手机验证码功能

1、输入手机号,点击发送后随机生成6位数字码,2分钟有效
2、输入验证码,点击验证,返回成功或者失败
3、每个手机号每天只能输入三次
这里

整合Spring-boot

1、添加依赖

<!--        redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
<!--        jedis-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>

2、yaml配置文件
我用的是jedis所以选了下type

spring:
  redis:
    host: 192.168.111.130
    client-type: jedis
    port: 6379

3、网页测试
成功显示。

@RestController
@RequestMapping("/user")
public class testRedis {
    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping("hello")
    public String testRedis() {
        //设置值到redis
        redisTemplate.opsForValue().set("name","syf");
        //从redis获取值
        String name = (String)redisTemplate.opsForValue().get("name");
        return name;
    }
}

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
				 	//基本配置  ip   redis端口号  连接超时时间
					jedisPool = new JedisPool(poolConfig, "192.168.111.130", 6379, 60000 );
				}
			}
		}
		return jedisPool;
	}

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

}

设置主从复制连接池

private static JedisSentinelPool jedisSentinelPool=null;

public static  Jedis getJedisFromSentinel(){
	if(jedisSentinelPool==null){
        Set<String> sentinelSet=new HashSet<>();
        sentinelSet.add("192.168.111.130:26379");//26379为哨兵模式开启后的端口号,192.168.111.130为Linux的ip

        jedisPoolConfig =new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(10); //最大可用连接数
		jedisPoolConfig.setMaxIdle(5); //最大闲置连接数
		jedisPoolConfig.setMinIdle(5); //最小闲置连接数
		jedisPoolConfig.setBlockWhenExhausted(true); //连接耗尽是否等待
		jedisPoolConfig.setMaxWaitMillis(2000); //等待时间
		jedisPoolConfig.setTestOnBorrow(true); //取连接的时候进行一下测试 ping pong

		jedisSentinelPool=new JedisSentinelPool("mymaster",sentinelSet,jedisPoolConfig);//mymaster为对监控主机的外号
		return jedisSentinelPool.getResource();
        }else{
				return jedisSentinelPool.getResource();
        }
}

集群的Jedis开发

/**
 * Redis集群
 */
public class RedisCluster {
    public static void main(String[] args) {
        //相当于redis-cli -c -p 6379连接集群
        HostAndPort hostAndPort = new HostAndPort("192.168.111.130", 6379);//端口号填任意一个都行,因为它可以自动切换
        //这三行也行,两种方法
//        Set<HostAndPort> set=new HashSet<>();
//        set.add(hostAndPort);
//        JedisCluster jedisCluster=new JedisCluster(set);
        //创建JedisCluster对象
        JedisCluster jedisCluster=new JedisCluster(hostAndPort);
        //操作
        jedisCluster.set("o","value");
        String value=jedisCluster.get("b1");
        System.out.println("value:"+value);
    }
}

分布式锁

UUID防误删锁

    public void testLock(){
        //生成一个锁的id
        String uuid = UUID.randomUUID().toString();
        //1获取锁,setIfAbsent相当于setne
        Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid,3, TimeUnit.SECONDS);//3为时间 TimeUnit.SECONDS为时间单位
        //2获取锁成功、查询num的值
        if(lock){
            Object value = redisTemplate.opsForValue().get("num");
            //2.1判断num为空return
            if(StringUtils.isEmpty(value)){
                return;
            }
            //2.2有值就转成成int
            int num = Integer.parseInt(value+"");
            //2.3把redis的num加1
            redisTemplate.opsForValue().set("num", ++num);
            //2.4释放锁,del
            //判断比较uuid值是否一样
            String lockUuid = (String)redisTemplate.opsForValue().get("lock");
            if(null!=lockUuid&&lockUuid.equals(uuid)) {
                redisTemplate.delete("lock");
            }
        }else{
            //3获取锁失败、每隔0.1秒再获取
            try {
                Thread.sleep(100);
                testLock();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

LUA脚本保证删除的原子性

    public void testLockLua() {
        //1 声明一个uuid ,将做为一个value 放入我们的key所对应的值中
        String uuid = UUID.randomUUID().toString();
        //2 定义一个锁:lua 脚本可以使用同一把锁,来实现删除!
        String skuId = "25"; // 访问skuId 为25号的商品 100008348542
        String locKey = "lock:" + skuId; // 锁住的是每个商品的数据

        // 3 获取锁
        Boolean lock = redisTemplate.opsForValue().setIfAbsent(locKey, uuid, 3, TimeUnit.SECONDS);

        // 第一种: lock 与过期时间中间不写任何的代码。
        // redisTemplate.expire("lock",10, TimeUnit.SECONDS);//设置过期时间
        // 如果true
        if (lock) {
            // 执行的业务逻辑开始
            // 获取缓存中的num 数据
            Object value = redisTemplate.opsForValue().get("num");
            // 如果是空直接返回
            if (StringUtils.isEmpty(value)) {
                return;
            }
            // 不是空 如果说在这出现了异常! 那么delete 就删除失败! 也就是说锁永远存在!
            int num = Integer.parseInt(value + "");
            // 使num 每次+1 放入缓存
            redisTemplate.opsForValue().set("num", String.valueOf(++num));
            /*使用lua脚本来锁*/
            // 定义lua 脚本
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            // 使用redis执行lua执行
            DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
            redisScript.setScriptText(script);
            // 设置一下返回值类型 为Long
            // 因为删除判断的时候,返回的0,给其封装为数据类型。如果不封装那么默认返回String 类型,
            // 那么返回字符串与0 会有发生错误。
            redisScript.setResultType(Long.class);
            // 第一个要是script 脚本 ,第二个需要判断的key,第三个就是key所对应的值。
            redisTemplate.execute(redisScript, Arrays.asList(locKey), uuid);
        } else {
            // 其他线程等待
            try {
                // 睡眠
                Thread.sleep(1000);
                // 睡醒了之后,调用方法。
                testLockLua();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

syf_wfl

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

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

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

打赏作者

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

抵扣说明:

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

余额充值