Redis实用篇(结合场景落地实现)

编程入门 行业动态 更新时间:2024-10-28 18:28:04

Redis实用篇(结合<a href=https://www.elefans.com/category/jswz/34/1770727.html style=场景落地实现)"/>

Redis实用篇(结合场景落地实现)

1. Redis作为查询缓存

以查询热点商品为例:
在查询热点商品的场景中,可以使用Redis来实现缓存功能,以减轻MySQL数据库的负担。

  1. 添加依赖。

确保Spring Boot项目已经配置了StringRedisTemplate。通常,需要在配置文件中配置Redis的连接信息。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
spring:redis:host: 你的RedisIP地址password: 你的Redis授权密码
  1. 创建一个热点商品服务,其中包含查询热点商品的功能。

使用StringRedisTemplate来处理热点商品的缓存。热点商品数据存储在Redis的哈希结构中,其中键是"HOT_PRODUCTS",字段是产品ID,值是产品信息。在getHotProduct方法中,我们首先尝试从缓存中获取商品信息,如果缓存中存在,就返回缓存中的数据;如果缓存中不存在,就从MySQL查询商品信息,然后将查询结果写回缓存。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;@Service
public class HotProductService {private static final String HOT_PRODUCT_KEY = "hot_products";@Autowiredprivate StringRedisTemplate stringRedisTemplate;// 查询热点商品,如果缓存中存在则从缓存获取,否则从MySQL查询并写回缓存public String getHotProduct(String productId) {String cachedProduct = stringRedisTemplate.opsForHash().get(HOT_PRODUCT_KEY, productId);if (cachedProduct != null) {return cachedProduct;} else {// 如果缓存中不存在,从MySQL查询String productFromDatabase = queryProductFromDatabase(productId);// 将查询结果写回缓存stringRedisTemplate.opsForHash().put(HOT_PRODUCT_KEY, productId, productFromDatabase);return productFromDatabase;}}// 模拟从MySQL查询商品信息的方法private String queryProductFromDatabase(String productId) {// 实际场景中,这里会查询MySQL数据库并返回商品信息// 这里使用一个简单的示例,返回一个模拟的商品信息return "Product: " + productId;}
}
  1. 使用热点商品服务。

在控制器或其他业务逻辑中,可以使用热点商品服务来实现热点商品的查询:
在这个控制器中,用户可以通过HTTP请求来查询热点商品的信息。如果商品信息已经被缓存,将从缓存中获取,否则将查询数据库并写入缓存。

@RestController
@RequestMapping("/hot-products")
public class HotProductController {@Autowiredprivate HotProductService hotProductService;@GetMapping("/{productId}")public ResponseEntity<String> getHotProduct(@PathVariable String productId) {String productInfo = hotProductService.getHotProduct(productId);return ResponseEntity.ok(productInfo);}
}

2. 使用Redis实现短信验证登陆

大致思路:使用StringRedisTemplate编写业务逻辑,实现登录控制功能,要求用户输入电话号,获取验证码,后台生成验证码并将验证码存储在Redis中,有效期5分钟。当用户在5分钟内输入正确的验证码,验证通过,然后从MySQL查询用户信息是否存在,如果存在,根据用户信息生成Token,以Token为key将用户信息放入Redis缓存,并将Token返回给用户客户端;如果用户不存在,就根据用户的电话号码生成一个用户信息到插入到MySQL,并生成Token,将用户信息存储到Redis,并将Token返回给用户客户端;用户登录成功后,将用户信息存储到ThreadLocal内。

  1. 添加依赖:
    确保Spring Boot项目已经配置了StringRedisTemplate,并且添加必要的依赖,包括Spring Web、Spring Data JPA(用于操作MySQL)、以及验证码生成工具(如Google’s Guava)。

  2. 编写验证码和登录服务:
    创建一个服务,包含生成验证码、验证验证码、查询用户信息、生成Token等功能。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;@Service
public class AuthService {private static final String VERIFICATION_CODE_KEY = "verification_code:";private static final String USER_INFO_KEY = "user_info:";@Autowiredprivate StringRedisTemplate stringRedisTemplate;// 生成验证码并存储到Redis,设置有效期为5分钟public String generateVerificationCode(String phoneNumber) {String code = generateRandomCode();String key = VERIFICATION_CODE_KEY + phoneNumber;stringRedisTemplate.opsForValue().set(key, code, 300, TimeUnit.SECONDS);return code;}// 验证验证码public boolean verifyVerificationCode(String phoneNumber, String code) {String key = VERIFICATION_CODE_KEY + phoneNumber;String storedCode = stringRedisTemplate.opsForValue().get(key);return code != null && code.equals(storedCode);}// 查询用户信息,如果用户不存在则插入到MySQLpublic UserInfo getUserInfo(String phoneNumber) {String key = USER_INFO_KEY + phoneNumber;UserInfo userInfo = stringRedisTemplate.opsForValue().get(key);if (userInfo == null) {userInfo = getUserInfoFromDatabase(phoneNumber);stringRedisTemplate.opsForValue().set(key, userInfo);}return userInfo;}// 生成Token并将用户信息存储到Redispublic String generateAndStoreToken(UserInfo userInfo) {String token = generateToken();String key = "token:" + token;stringRedisTemplate.opsForValue().set(key, userInfo, 24, TimeUnit.HOURS); // 设置Token有效期为24小时return token;}private String generateRandomCode() {// 实现生成随机验证码的逻辑,可以使用Guava或其他工具return "123456"; // 示例:固定验证码为123456}private UserInfo getUserInfoFromDatabase(String phoneNumber) {// 查询MySQL数据库,如果用户存在,则返回用户信息,否则插入新用户并返回用户信息// 实际场景中,需要使用Spring Data JPA或其他数据库访问方式return new UserInfo(phoneNumber, "User Name"); // 示例:生成用户信息}private String generateToken() {// 实现生成Token的逻辑,可以使用UUID或其他方式return UUID.randomUUID().toString(); // 示例:使用UUID生成Token}
}
  1. 控制器:
    创建一个控制器,用于处理用户请求,包括获取验证码、验证验证码和登录。
@RestController
@RequestMapping("/auth")
public class AuthController {@Autowiredprivate AuthService authService;// 获取验证码@GetMapping("/get-verification-code")public ResponseEntity<String> getVerificationCode(@RequestParam String phoneNumber) {String code = authService.generateVerificationCode(phoneNumber);return ResponseEntity.ok("Verification code sent: " + code);}// 验证验证码并登录@PostMapping("/login")public ResponseEntity<String> login(@RequestParam String phoneNumber, @RequestParam String code) {if (authService.verifyVerificationCode(phoneNumber, code)) {UserInfo userInfo = authService.getUserInfo(phoneNumber);String token = authService.generateAndStoreToken(userInfo);// 将用户信息存储到ThreadLocalThreadLocalUserInfo.setUserInfo(userInfo);return ResponseEntity.ok("Login successful. Token: " + token);} else {return ResponseEntity.badRequest().body("Invalid verification code.");}}
}

用户可以通过HTTP请求获取验证码和登录。如果验证码验证通过,将生成Token并将用户信息存储到ThreadLocal中,以便在请求处理过程中使用。

3.Redis实现分布式锁

分布式锁可以用于确保在多个应用实例之间,只有一个实例可以执行更新操作,以避免竞争条件。

用户可以通过HTTP请求模拟更新库存的操作。在更新库存之前,首先尝试获取分布式锁,如果成功获取到锁,则执行库存更新操作,然后释放锁。如果无法获取锁,表示有其他实例正在执行更新操作,返回冲突状态码(HTTP 409)。

  1. 添加依赖:
    确保你的Spring Boot项目已经配置了StringRedisTemplate,以及在项目中引入相关的Redis依赖。
  2. 编写分布式锁和库存更新服务:
    创建一个服务,包含获取锁、释放锁以及更新库存的操作。
    我们使用StringRedisTemplate来实现分布式锁和更新库存。acquireLock方法尝试获取锁,如果成功获取到锁,返回true,否则返回false。releaseLock方法用于释放锁。updateInventory方法用于更新商品库存。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;@Service
public class InventoryService {private static final String LOCK_KEY = "inventory_lock";private static final String INVENTORY_KEY = "inventory";@Autowiredprivate StringRedisTemplate stringRedisTemplate;// 获取分布式锁public boolean acquireLock() {Boolean success = stringRedisTemplate.opsForValue().setIfAbsent(LOCK_KEY, "locked");if (success != null && success) {return true;}return false;}// 释放分布式锁public void releaseLock() {stringRedisTemplate.delete(LOCK_KEY);}// 更新商品库存public boolean updateInventory(int quantity) {String inventoryStr = stringRedisTemplate.opsForValue().get(INVENTORY_KEY);if (inventoryStr != null) {int currentInventory = Integer.parseInt(inventoryStr);int newInventory = currentInventory + quantity;stringRedisTemplate.opsForValue().set(INVENTORY_KEY, String.valueOf(newInventory));return true;}return false;}
}
  1. 控制器:
    创建一个控制器,用于模拟更新库存的请求。
@RestController
@RequestMapping("/inventory")
public class InventoryController {@Autowiredprivate InventoryService inventoryService;@PostMapping("/update")public ResponseEntity<String> updateInventory(@RequestParam int quantity) {if (inventoryService.acquireLock()) {try {boolean success = inventoryService.updateInventory(quantity);if (success) {return ResponseEntity.ok("Inventory updated successfully.");} else {return ResponseEntity.badRequest().body("Failed to update inventory.");}} finally {inventoryService.releaseLock();}} else {return ResponseEntity.status(HttpStatus.CONFLICT).body("Inventory update in progress.");}}
}

4.使用Redis获取附近的饭店信息

要使用Redis实现获取附近的饭店信息,你可以结合地理空间索引功能,Redis提供了Geospatial数据类型,如有序集合(Sorted Set)来存储地理位置数据。

  1. 存储饭店信息:
    首先,你需要将饭店的位置信息存储在Redis中。你可以使用有序集合(Sorted Set)来存储,将饭店的经度和纬度作为分数(score),饭店的名称或ID作为成员(member)。例如:
// 添加饭店的位置信息到有序集合
stringRedisTemplate.opsForZSet().add("restaurants", "Restaurant A", new GeoCoordinate(13.361389, 38.115556));
stringRedisTemplate.opsForZSet().add("restaurants", "Restaurant B", new GeoCoordinate(15.087269, 37.502669));
// ...添加更多饭店的位置信息
  1. 查询附近的饭店:
    现在,你可以使用Redis的Geospatial命令来查询附近的饭店。例如,你可以使用GEORADIUS命令来查找指定位置附近一定范围内的饭店:
// 查找离指定经度和纬度坐标10千米范围内的饭店
List<GeoResult<GeoLocation<String>>> restaurants = stringRedisTemplate.opsForGeo().radius("restaurants", new Circle(new Point(13.361389, 38.115556), new Distance(10, Metrics.KILOMETERS)));

上述代码会返回一个GeoResult列表,其中包含了附近饭店的信息,包括名称和距离等。

  1. 显示饭店信息:
    遍历GeoResult列表,将附近的饭店信息显示给用户。可以根据具体需求来展示饭店的名称、距离等信息。

这只是一个简单的示例,实际中你可能需要更复杂的逻辑,如根据用户当前位置、提供排序、筛选等功能。另外,为了减少网络延迟,通常可以将附近饭店的信息缓存在应用程序中,定期从Redis中刷新。此外,可以考虑使用其他地理空间索引数据库如MongoDB或专用的地理信息服务提供商如Mapbox,以获得更多高级的地理查询功能。

5.使用Redis获取共同好友

要使用Redis获取共同好友,你可以使用Redis的集合数据结构来存储每个用户的好友列表,并使用集合操作来查找两个用户的共同好友。以下是一个基本的实现思路:

  1. 存储用户和好友关系:
    首先,你需要将每个用户的好友列表存储在Redis中。通常,你可以使用Redis的集合数据结构,例如SADD命令来添加好友到用户的好友列表中。
// 用户A的好友列表
stringRedisTemplate.opsForSet().add("user:A:friends", "B", "C", "D");
// 用户B的好友列表
stringRedisTemplate.opsForSet().add("user:B:friends", "A", "C", "E");
// ... 添加更多用户和好友关系
  1. 查找共同好友:
    现在,你可以使用Redis的集合操作命令来查找两个用户的共同好友。例如,你可以使用SINTER命令来获取两个用户的共同好友。
// 查找用户A和用户B的共同好友
Set<String> commonFriends = stringRedisTemplate.opsForSet().intersect("user:A:friends", "user:B:friends");

commonFriends集合中包含了用户A和用户B的共同好友。

  1. 显示共同好友:
    遍历commonFriends集合,将共同好友的名称显示给用户。根据需求,你可以在应用程序中进一步处理共同好友的信息。

实际中你可能需要更复杂的逻辑,如支持分页、提供搜索功能、处理用户关系的变化等。另外,你可以考虑使用Redis的有序集合数据结构来存储好友列表,并为每个好友指定一个分数,以支持更复杂的好友关系操作。

6.使用Redis实现会议签到功能

使用Redis实现会议签到功能是一种常见的用例,其中Redis可以用作临时存储签到信息和记录会议参与者的状态。以下是一个示例,演示如何使用Redis实现会议签到功能:

  1. 存储会议信息和签到记录:

首先,你需要在Redis中存储会议信息以及签到记录。你可以使用Redis的哈希(Hash)数据结构来存储会议信息,以及有序集合(Sorted Set)来存储签到记录。例如:

// 存储会议信息
stringRedisTemplate.opsForHash().put("meeting:123", "name", "Team Meeting");
stringRedisTemplate.opsForHash().put("meeting:123", "location", "Conference Room A");// 记录签到
stringRedisTemplate.opsForZSet().add("meeting:123:attendees", "user:A", System.currentTimeMillis());
stringRedisTemplate.opsForZSet().add("meeting:123:attendees", "user:B", System.currentTimeMillis());
// ... 添加更多签到记录
  1. 签到:

当会议参与者到达会议现场时,可以执行签到操作。签到时,你可以添加用户到会议的有序集合中,并记录签到的时间戳。

String userId = "user:C";
String meetingId = "meeting:123";
stringRedisTemplate.opsForZSet().add(meetingId + ":attendees", userId, System.currentTimeMillis());
  1. 查询签到记录:

你可以使用有序集合操作来查询会议的签到记录。例如,你可以使用ZRANGE命令来获取签到用户列表。

String meetingId = "meeting:123";
Set<String> attendees = stringRedisTemplate.opsForZSet().range(meetingId + ":attendees", 0, -1);

attendees集合中包含了所有签到的用户。

  1. 检查签到状态:

你可以通过检查用户是否在会议的有序集合中来确定其签到状态。

String userId = "user:D";
String meetingId = "meeting:123";
Boolean isAttended = stringRedisTemplate.opsForZSet().score(meetingId + ":attendees", userId) != null;

isAttended将返回true表示用户已签到,返回false表示用户未签到。

这只是一个简单的示例,实际中,你可能需要更多的功能,如处理签到状态的变化、签到时间的统计、检查会议是否已经开始等。使用Redis来实现会议签到功能可以提供快速的读写操作,但也需要考虑并发处理、数据保护等问题。根据具体需求,你可以设计更复杂的签到系统。

更多推荐

Redis实用篇(结合场景落地实现)

本文发布于:2023-12-04 00:47:21,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1659264.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:场景   Redis

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!