102.【Redis】(五)

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 102.【Redis】

(六)、Redis监控/乐观锁(watch)

1、悲观锁:顾名思义就是做什么事情都很悲观,无论干什么都要上锁。(影响性能的)

2、乐观锁:做什么事都很乐观,都不会去上锁;只有更新数据的时候去才判断一下version,看一下在此期间是否有人修改过这个数据:

  • 获取version
  • 更新的时候比较version

使用watch key监控指定数据,相当于乐观锁加锁。

1.正常执行乐观锁

单线程执行成功!

127.0.0.1:6379> set money 100   #设置余额100
OK
127.0.0.1:6379> set out 0  # 发出 0
OK
127.0.0.1:6379> watch money # 开始监视余额
OK
127.0.0.1:6379> multi  # 开启事务
OK
127.0.0.1:6379(TX)> decrby money 20  # 画出20
QUEUED
127.0.0.1:6379(TX)> incrby out 20
QUEUED
127.0.0.1:6379(TX)> EXEC  #结束
1) (integer) 80
2) (integer) 20

2.多线程执行乐观锁

一个服务器,两个客户端

第一个线程,继续监视money,然后开启事务设置操作**但不提交**

127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 10
QUEUED
127.0.0.1:6379(TX)> INCRBY out 10
QUEUED
127.0.0.1:6379(TX)>

第二个线程 进行充值1000元人民币

127.0.0.1:6379> get money
"80"
127.0.0.1:6379> set money 1000
OK
127.0.0.1:6379> get money
"1000"

然后第一个线程提交事务,发现会出错

127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 10
QUEUED
127.0.0.1:6379(TX)> INCRBY out 10
QUEUED
127.0.0.1:6379(TX)> EXEC  # 提交事务,但是出错
(nil)

无论事务是否执行成功,Redis都会取消watch监控

如果发现事务执行失败,我们需要先解锁。

127.0.0.1:6379> unwatch  # 解锁
OK
127.0.0.1:6379> watch money  # 重新上锁
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> DECRBY money 10
QUEUED
127.0.0.1:6379(TX)> INCRBY out 10
QUEUED
127.0.0.1:6379(TX)> EXEC
1) (integer) 990
2) (integer) 30

注意:

  • 如果发现事务执行失败就先解锁 unwatch
  • 获取最新的值,再次进行监视 watch key
  • 比对监视的值是否发生了变化,如果没有变化那么可以执行成功,反之则会失败。

(七)、Jedis

Jedis是Redis官方推荐使用的Java连接redis的客户端。所以我们在使用Java来操作redis时就要学习Jedis。

1.导入相关的依赖

首先设置一个空项目,然后创建一个Maven项目

<dependencies>
        <!--导入jredis的包-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.2.0</version>
        </dependency>
        <!--fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.70</version>
        </dependency>
    </dependencies>

2.测试远程Redis

假如说连接Linux系统。

  1. 注释掉配置文件中的 bind 127.0.0.1
  2. daemonize 设置为no
  3. 阿里云开启安全组6379 宝塔也要开启6379
  4. 要开启服务端的redis
  5. 一定要设置密码 否则容易被黑。

测试:

package com.jsxs;
import redis.clients.jedis.Jedis;
public class testPing {
    public static void main(String[] args) {
        // 1. new Jedis对象
        Jedis jedis = new Jedis("IP", 6379);
        jedis.auth("密码");  
        System.out.println(jedis.ping());
    }
}

输出

package com.jsxs;
import redis.clients.jedis.Jedis;
public class testPing {
    public static void main(String[] args) {
        // 1. new Jedis对象
        Jedis jedis = new Jedis("IP", 6379);
        jedis.auth("密码");
        // 2.测试是否链接成功
        System.out.println(jedis.ping());
        System.out.println("清空数据库->"+ jedis.flushDB());
        System.out.println("判断某一个值是否存在->"+ jedis.exists("username"));
        System.out.println("新增一个键值对->"+jedis.set("username","jsxs"));
        System.out.println("新增一个键值对->"+ jedis.set("password","15945"));
        System.out.println("获取全部键值对"+jedis.keys("*"));
        System.out.println("获取范围内的值"+jedis.getrange("username",0,1));
    }
}

3.事务相关案列

事务相关举列

成功案列事务

package com.jsxs;
import com.alibaba.fastjson.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
public class testTX {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("8.130.48.9", 6379);
        jedis.auth("121788");
        System.out.println(jedis.ping());
        // 设置JSON数据
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("hello","world");
        jsonObject.put("name","jsxs");
        Transaction multi = jedis.multi();//开启事务
        String result = jsonObject.toJSONString(); //把JSON数据转换为字符串
        try {
            multi.set("user1",result);
            multi.set("user2",result);
            multi.exec(); //假如成功就执行
        } catch (Exception e) {
            multi.discard();   //假如执行失败,就取消事务
            e.printStackTrace();
        } finally {
            System.out.println(jedis.get("user1"));
            System.out.println(jedis.get("user2"));
            jedis.close();  //最终都关闭客户端
        }
    }
}

事务失败

package com.jsxs;
import com.alibaba.fastjson.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
public class testTX {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("8.130.48.9", 6379);
        jedis.auth("121788");
        System.out.println(jedis.ping());
        jedis.flushDB();
        // 设置JSON数据
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("hello","world");
        jsonObject.put("name","jsxs");
        Transaction multi = jedis.multi();//开启事务
        String result = jsonObject.toJSONString(); //把JSON数据转换为字符串
        try {
            multi.set("user1",result);
            multi.set("user2",result);
            int i=1/0;
            multi.exec(); //假如成功就执行
        } catch (Exception e) {
            multi.discard();   //假如执行失败,就取消事务
            System.out.println("事务执行失败");
            e.printStackTrace();
        } finally {
            System.out.println(jedis.get("user1"));
            System.out.println(jedis.get("user2"));
            jedis.close();  //最终都关闭客户端
        }
    }
}

(八)、SpringBoot整合Redis

1.导入一个整合包

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

说明: 在SpringBoot2.x之后,原来使用的jedis被替换为了lettuce.

  • jedis: 采用的是直连,多个线程操作的话,是不安全的,如果想要避免不安全的,使用jedis oppl连接池,更像BIO模式。
  • lerruce: 采用netty,实列可以在多个线程中进行共享,不存在线程不安全的情况,可以减少线程数据了,更像NIO模式
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
27天前
|
NoSQL Redis
Redis系列
(1)完全基于内存操作,数据都存在内存中 (2)采用单线程,避免了不必要的上下文切换带来的性能问题,也不用考虑锁的问题 (3)基于非阻塞的io多路复用机制 (4)数据结构简单,对数据操作简单
|
存储 缓存 NoSQL
|
存储 消息中间件 NoSQL
什么是Redis?
redis是一个高性能的key-value数据库。
80 0
|
存储 缓存 NoSQL
Redis5
Redis5
125 0
|
消息中间件 NoSQL 测试技术
Redis2
Redis2
129 0
|
存储 消息中间件 缓存
了解redis
了解redis
80 0
|
NoSQL Redis
|
NoSQL 程序员 数据库
|
消息中间件 缓存 NoSQL
Redis详解(一)冰叔带你了解Redis
Redis详解(一)冰叔带你了解Redis
197 0
|
存储 缓存 监控
Redis应用问题解决
key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会压到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。
Redis应用问题解决