Spring Boot整合 NoSQL 数据库 Redis详解

下面我会给您讲解一下“Spring Boot整合 NoSQL 数据库 Redis”的完整攻略。

简介

Redis是一个基于内存的高性能key-value数据库,支持多种数据类型,可应用于缓存、消息队列、实时统计等场景。在Spring Boot应用中,我们可以很方便地集成Redis来实现快速高效的数据存取。

环境配置

要使用Redis,首先需要在本地安装Redis服务,可以去Redis官网下载并安装。安装完成后,启动Redis服务即可。

在Spring Boot项目中,我们需要引入Redis的依赖。可以在pom.xml文件中添加以下内容:

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

Redis配置

在Spring Boot项目中,我们需要在application.properties文件中配置Redis连接信息,如下所示:

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password= # 如果Redis服务设置了密码,则需要填写密码信息

使用Redis

在Spring Boot项目中,可以通过注入RedisTemplate对象来使用Redis。RedisTemplate是Spring封装的Redis客户端,提供了一组操作Redis数据的方法。

以保存一个String类型的值为例,示例代码如下:

@Autowired
private RedisTemplate<String, String> redisTemplate;

public void save(String key, String value) {
    redisTemplate.opsForValue().set(key, value);
}

上面的代码中,redisTemplate.opsForValue()方法返回一个ValueOperations对象,可以使用这个对象来操作String类型的数据。set方法用于保存一个键值对。

示例一

下面我们通过一个简单示例来展示如何使用Redis实现缓存信息的存取。

首先定义一个用于查询员工信息的接口:

public interface EmployeeService {
    Employee getEmployeeById(Long id);
}

然后实现这个接口,这里我们通过休眠2秒钟的方式,模拟查询员工信息的耗时:

@Service
public class EmployeeServiceImpl implements EmployeeService {

    @Override
    public Employee getEmployeeById(Long id) {
        // 这里休眠2秒钟,模拟查询员工信息的耗时
        try {
            Thread.sleep(2000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return new Employee(id, "张三", 30);
    }
}

接下来,我们定义一个用于缓存员工信息的接口:

public interface EmployeeCache {
    Employee getEmployeeById(Long id);
    void putEmployee(Employee employee);
}

然后通过Redis实现这个接口:

@Service
public class EmployeeCacheRedisImpl implements EmployeeCache {

    @Autowired
    private RedisTemplate<String, Employee> redisTemplate;

    @Override
    public Employee getEmployeeById(Long id) {
        String key = "employee:" + id;
        if (redisTemplate.hasKey(key)) {
            return redisTemplate.opsForValue().get(key);
        }

        Employee employee = getEmployeeFromDB(id);
        redisTemplate.opsForValue().set(key, employee);
        return employee;
    }

    @Override
    public void putEmployee(Employee employee) {
        String key = "employee:" + employee.getId();
        redisTemplate.opsForValue().set(key, employee);
    }

    private Employee getEmployeeFromDB(Long id) {
        // 这里只是简单模拟,实际开发中不应该这样做
        return new Employee(id, "张三", 30);
    }
}

上面的代码中,我们在getEmployeeById方法中,先从Redis缓存中获取员工信息,如果不存在,则通过getEmployeeFromDB方法从数据库中查询员工信息,并将查询结果保存到Redis缓存中。在保存到Redis缓存中时,我们使用了一个前缀employee:来区分不同的缓存信息。

最后,我们可以在Controller中使用这些接口:

@RestController
@RequestMapping("/employee")
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    @Autowired
    private EmployeeCache employeeCache;

    @GetMapping("/{id}")
    public Employee getEmployeeById(@PathVariable("id") Long id) {
        // 先从缓存中获取员工信息
        Employee employee = employeeCache.getEmployeeById(id);
        if (employee != null) {
            return employee;
        }

        // 如果缓存中不存在,则从数据库中获取员工信息,并保存到缓存中
        employee = employeeService.getEmployeeById(id);
        if (employee != null) {
            employeeCache.putEmployee(employee);
        }

        return employee;
    }
}

上面的代码中,我们先从缓存中获取员工信息,如果缓存中不存在,则通过getEmployeeById方法从数据库中获取,并将查询结果保存到缓存中。

示例二

接下来我们通过另一个简单示例来展示如何在Redis中使用Lua脚本。

首先定义一个用于扣减库存的接口:

public interface InventoryService {
    boolean reduceInventory(String sku, int quantity);
}

然后实现这个接口,这里我们使用了Redis中的decrBy命令来扣减库存,但是这个命令是原子操作,可能存在并发问题:

@Service
public class InventoryServiceImpl implements InventoryService {

    @Autowired
    private RedisTemplate<String, Integer> redisTemplate;

    @Override
    public boolean reduceInventory(String sku, int quantity) {
        String key = "inventory:" + sku;
        Integer stock = redisTemplate.opsForValue().get(key);
        if (stock == null || stock < quantity) {
            return false;
        }

        redisTemplate.opsForValue().decrement(key, quantity);
        return true;
    }
}

为了解决并发问题,我们可以使用Redis中的Lua脚本。Lua脚本可以保证操作的原子性,而且执行速度也很快。

我们可以将扣减库存的代码改写为Lua脚本,如下所示:

@Service
public class InventoryServiceImpl implements InventoryService {

    @Autowired
    private RedisTemplate<String, Integer> redisTemplate;

    @Override
    public boolean reduceInventory(String sku, int quantity) {
        String key = "inventory:" + sku;
        Integer stock = redisTemplate.opsForValue().get(key);
        if (stock == null || stock < quantity) {
            return false;
        }

        String script = "if redis.call('get', KEYS[1]) >= tonumber(ARGV[1]) then return redis.call('decrby', KEYS[1], ARGV[1]) else return 0 end";
        List<String> keys = new ArrayList<>();
        keys.add(key);
        List<String> args = new ArrayList<>();
        args.add(String.valueOf(quantity));
        Long result = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), keys, args);
        return result != null && result > 0;
    }
}

上面的代码中,我们使用了DefaultRedisScript对象来执行Lua脚本。在脚本中,我们首先判断库存是否足够,如果足够,则使用decrBy命令扣减库存。注意,在decrBy命令中,我们使用了ARGV[1]来表示传入的扣减数量。如果库存不足,则返回0。

最后,我们可以在Controller中使用这个接口:

@RestController
@RequestMapping("/inventory")
public class InventoryController {

    @Autowired
    private InventoryService inventoryService;

    @PostMapping("/reduce")
    public boolean reduceInventory(@RequestParam("sku") String sku, @RequestParam("quantity") int quantity) {
        return inventoryService.reduceInventory(sku, quantity);
    }
}

上面的代码中,我们通过POST请求来扣减库存。传入的参数包括产品SKU和扣减数量。

以上是关于Spring Boot整合Redis的完整攻略,提供了两个示例。希望可以对您有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Boot整合 NoSQL 数据库 Redis详解 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • MySQL 数据库(二):增、删、改语法

    掌握往表里插入数据的 sql 命令(insert) 掌握修改表数据的 sql 命令(update) 掌握删除数据库,表,数据的 sql 命令(drop, delete) 增 插入表数据(insert)语法: 插入一条数据,对所有字段都赋值: insert into 表名 values (值A,值B,值C,值D,值E); 插入一条数据,直插入部分字段的值 in…

    MySQL 2023年4月13日
    00
  • MySQL中如何增加字段SQL语句

    在MySQL中增加字段的SQL语句可以通过ALTER TABLE命令来实现。具体步骤如下: 打开MySQL命令行,连接到对应的数据库 mysql -u username -p password USE database_name; 使用ALTER TABLE命令增加字段,语法如下: ALTER TABLE `table_name` ADD COLUMN `c…

    database 2023年5月22日
    00
  • Mysql日期格式以及内置日期函数用法详解

    Mysql日期格式 在Mysql中,日期数据类型包括DATE、TIME、DATETIME、TIMESTAMP、YEAR五种,它们都有各自的日期格式。 DATE DATE类型存储格式为’YYYY-MM-DD’。 例如: 2022-01-01 TIME TIME类型存储格式为’hh:mm:ss’。 例如: 14:30:00 DATETIME DATETIME类型…

    database 2023年5月22日
    00
  • Oracle to_char 日期转换字符串语句分享

    当需要将日期格式的数据转换为字符串时,Oracle数据库提供了to_char函数来完成此操作。以下是to_char函数的语法: TO_CHAR( date, format_mask [, nls_language ] ) 其中,date参数是要转换的日期,format_mask是要转换为的字符串的格式,nls_language是可选参数,用于指定语言环境。下…

    database 2023年5月21日
    00
  • oracle—SQL技巧之(一)连续记录查询sql案例测试

    下面是详细讲解“oracle—SQL技巧之(一)连续记录查询sql案例测试”的完整攻略。 标题 文章标题是“oracle—SQL技巧之(一)连续记录查询sql案例测试”,它表明这篇文章是介绍我们如何使用SQL技巧在oracle数据库中查询连续记录的。 简介 在SQL查询中,有时我们需要查询连续的记录,例如查询某个时间范围内的销售记录等。本篇文章将会介绍如何使…

    database 2023年5月21日
    00
  • Android编程操作嵌入式关系型SQLite数据库实例详解

    Android编程操作嵌入式关系型SQLite数据库实例详解 什么是SQLite数据库 SQLite是一种轻型的关系型数据库。与其他数据库不同,SQLite是嵌入式的数据库,它不需要独立的服务器进程或配置,而直接读取或写入普通文件。这使得SQLite非常适用于需要轻量级、快速、可靠的数据存储和检索的场景,包括Android应用。 在Android中使用SQL…

    database 2023年5月22日
    00
  • Python 基于Python从mysql表读取千万数据实践

    基于Python 从mysql表读取千万数据实践   by:授客 QQ:1033553122 场景:   有以下两个表,两者都有一个表字段,名为waybill_no,我们需要从tl_waybill_bar_record表读取1000w条唯一的waybill_no,然后作为INSERT SQL语句的一部分,填充到ts_order_waybill的waybill…

    MySQL 2023年4月13日
    00
  • Linux下将数据库从MySQL迁移到MariaDB的基础操作教程

    以下是详细讲解“Linux下将数据库从MySQL迁移到MariaDB的基础操作教程”的完整攻略。 基础操作教程 1. 安装MariaDB 在开始迁移之前,需要先安装MariaDB。可以在Linux系统中使用以下命令来安装: sudo apt-get install mariadb-server 2. 备份MySQL数据库 在迁移之前,需要备份MySQL数据库…

    database 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部