日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

Redis项目应用场景与实例汇总

發布時間:2023/12/9 数据库 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Redis项目应用场景与实例汇总 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 一、背景
    • 1.1 開發環境
    • 1.2 項目配置
  • 二、字符串的應用場景:封鎖一個IP地址
  • 三、Hash的應用場景:存儲用戶信息
  • 四、List的應用場景:隊列實現
  • 五、Set的應用場景:自動去重

一、背景

  • 本篇文章是將以前Redis實戰的系列文章進行匯總,針對Redis中常用的一些數據結構,進行實戰模擬。
stringshasheslistssetssorted sets
封鎖一個IP地址存儲用戶信息模擬消息隊列自動排重以某一個條件為權重,進行排序

1.1 開發環境

  • JDK 1.8
  • SpringBoot 2.2.5
  • JPA
  • Spring Security
  • Mysql 8.0
  • Redis Server 3.2.1
  • Redis Desktop Manager
  • Swagger2
  • 1.2 項目配置

    • SpringBoot集成Redis, 添加依賴
    <!--pom.xl--><!--Redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
    • 項目配置文件 添加redis連接配置
    <!-- application.yml--> server:port: 8000spring:freemarker:check-template-location: falseprofiles:active: devjackson:time-zone: GMT+8data:redis:repositories:enabled: false#配置 Jpajpa:properties:hibernate:dialect: org.hibernate.dialect.MySQL5InnoDBDialectopen-in-view: trueredis:database: 0host: 127.0.0.1port: 6379password:
    • 增加RedisConfig配置類
    /*** Redis配置類** @author zhuhuix*/ @Configuration @EnableCaching @ConditionalOnClass(RedisOperations.class) @EnableConfigurationProperties(RedisProperties.class) public class RedisConfig extends CachingConfigurerSupport {/***設置 redis 數據默認過期時間*/@Beanpublic RedisCacheConfiguration redisCacheConfiguration(){FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer)).entryTtl(Duration.ofHours(Constant.CACHE_TIMEOUT_HOUR));return configuration;}@Beanpublic RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<Object, Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);template.setValueSerializer(fastJsonRedisSerializer);template.setHashValueSerializer(fastJsonRedisSerializer);ParserConfig.getGlobalInstance().setAutoTypeSupport(true);template.setKeySerializer(new StringRedisSerializer());template.setHashKeySerializer(new StringRedisSerializer());template.afterPropertiesSet();return template;}/*** 參考:https://blog.csdn.net/qq_15071263/article/details/84335632* 自定義緩存key生成策略,默認將使用該策略*/@Bean@Overridepublic KeyGenerator keyGenerator() {return (target, method, params) -> {Map<String,Object> container = new HashMap<>(3);Class<?> targetClassClass = target.getClass();// 類地址container.put("class",targetClassClass.toGenericString());// 方法名稱container.put("methodName",method.getName());// 包名稱container.put("package",targetClassClass.getPackage());// 參數列表for (int i = 0; i < params.length; i++) {container.put(String.valueOf(i),params[i]);}// 轉為JSON字符串String jsonString = JSON.toJSONString(container);// 做SHA256 Hash計算,得到一個SHA256摘要作為Keyreturn DigestUtils.sha256Hex(jsonString);};}
    • 增加RedisUtils工具類:實現對各種數據結構的封裝
    /*** Redis工具類** @author zhuhuix*/ @Component @AllArgsConstructor public class RedisUtils {private RedisTemplate<Object, Object> redisTemplate;/*** HashGet根據鍵值得到對象** @param key 鍵值 @NotNull* @param item 項目 @NotNull* @return 對象*/public Object hashGet(String key, String item) {return redisTemplate.opsForHash().get(key, item);}/*** 根據鍵值向hash表中寫入對象** @param key 鍵值 @NotNull* @param item 項目 @NotNull* @param value 對象 @NotNull* @return true 成功 false失敗*/public boolean hashSet(String key, String item, Object value) {try {redisTemplate.opsForHash().put(key, item, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 根據鍵值向hash表中寫入對象,并設置過期時間** @param key 鍵值 @NotNull* @param item 項目 @NotNull* @param value 對象 @NotNull* @param time 過期時間(秒) @NotNull* @return true 成功 false失敗*/public boolean hashSet(String key, String item, Object value, long time) {try {redisTemplate.opsForHash().put(key, item, value);if (time > 0) {expire(key, time);}return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 根據鍵值對某一項目的進行累加計數** @param key 鍵值* @param l 累加數*/public long increment(String key, long l) {return redisTemplate.opsForValue().increment(key, l);}/*** 根據鍵值對某一項目的進行累加計數,并設置過期時間** @param key 鍵值* @param l 累加數* @param time 過期時間(秒)*/public long increment(String key, long l, long time) {long count = redisTemplate.opsForValue().increment(key, l);if (time > 0) {expire(key, time);}return count;}/*** 入隊** @param key 隊列鍵值* @param value 元素* @return 添加數量*/public long leftPush(String key, Object value) {return redisTemplate.opsForList().leftPush(key, value);}/*** 向隊列頭部添加全部集合元素** @param key 隊列鍵值* @param list 集合* @return 返回添加的數量*/public long leftPushAll(String key, List<Object> list) {return redisTemplate.opsForList().leftPushAll(key, list);}/*** 統計隊列中所有元素數量** @param key 隊列鍵值* @return 隊列中元素數量*/public long size(String key) {return redisTemplate.opsForList().size(key);}/*** 返回隊列中從起始位置到結束位置的集合元素** @param key 隊列鍵值* @param start 起始位置* @param end 結束位置* @return 返回集合*/public List<Object> range(String key, long start, long end) {return redisTemplate.opsForList().range(key, start, end);}/*** 出隊** @param key 隊列鍵值* @return 元素*/public Object rightPop(String key) {return redisTemplate.opsForList().rightPop(key);}/*** 彈出隊列最新元素** @param key 隊列鍵值* @return 元素*/public Object leftPop(String key) {return redisTemplate.opsForList().leftPop(key);}/*** 刪除隊列所有元素** @param key 隊列鍵值*/public void deleteAll(String key) {redisTemplate.opsForList().trim(key, 0, 0);redisTemplate.opsForList().leftPop(key);}/*** 向集合中增加元素** @param key 集合鍵值* @param value 元素* @return 添加數量*/public long setAdd(String key, Object value) {return redisTemplate.opsForSet().add(key,value);}/*** 向集合中批量增加元素** @param key 集合鍵值* @param list 元素列表* @return 添加數量*/public long setAdd(String key, List<Object> list) {return redisTemplate.opsForSet().add(key,list);}/*** 集合刪除指定元素** @param key 集合鍵值* @param value 指定元素* @return 刪除數量*/public long setRemove(String key, Object value) {return redisTemplate.opsForSet().remove(key, value);}/*** 集合批量刪除指定元素** @param key 集合鍵值* @param list 指定元素列表* @return 刪除數量*/public long setRemove(String key, List<Object> list) {return redisTemplate.opsForSet().remove(key, list);}/*** 取出兩信集合的交集** @param key1 集合1鍵值* @param key2 集合2鍵值* @return 交集*/public Set<Object> setInter(String key1, String key2) {return redisTemplate.opsForSet().intersect(key1, key2);}/*** 取出多個集合的交集** @param keys 鍵值列表* @return 交集*/public Set<Object> setInter(List<Object> keys) {return redisTemplate.opsForSet().intersect(keys);}/*** 取出兩個集合的差集** @param key1 集合1鍵值* @param key2 集合2鍵值* @return 差集*/public Set<Object> setDifference(String key1,String key2){return redisTemplate.opsForSet().difference(key1,key2);}/*** 指定緩存的失效時間** @param key 鍵值 @NotNull* @param time 時間(秒) @NotNull*/public boolean expire(String key, long time) {try {if (time > 0) {redisTemplate.expire(key, time, TimeUnit.SECONDS);}} catch (Exception e) {e.printStackTrace();return false;}return true;}}

    二、字符串的應用場景:封鎖一個IP地址

    • 創建SpringBoot后臺服務程序,實現用戶登錄及JWT認證;
    • 通過Redis緩存限制在1分鐘內同一IP請求登錄不能超過5次。

    • 登錄實現類增加Redis計數判斷
    /*** 授權登錄接口實現類** @author zhuhuix*/ @Slf4j @Service @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class AuthServiceImpl implements AuthService {@Value("${wxMini.appId}")private String appId;@Value("${wxMini.secret}")private String secret;private final JwtTokenUtils jwtTokenUtils;private final WxMiniApi wxMiniApi;private final UserService userService;private final JwtSecurityProperties properties;private final RedisUtils redisUtils;public AuthServiceImpl(JwtTokenUtils jwtTokenUtils, WxMiniApi wxMiniApi, UserService userService, JwtSecurityProperties properties, RedisUtils redisUtils) {this.jwtTokenUtils = jwtTokenUtils;this.wxMiniApi = wxMiniApi;this.userService = userService;this.properties = properties;this.redisUtils = redisUtils;}@Override@Transactional(rollbackFor = Exception.class)public Result<AuthUserDto> login(AuthUserDto authUserDto, HttpServletRequest request) {// 通過緩存判斷同一IP某一時間段內的登錄次數是否超出限定次數String ip = NetworkUtils.getIp(request);String requestLoginIp = "request_login_".concat(ip);long loginCount = redisUtils.increment(requestLoginIp, 1L);if (loginCount == 1) {redisUtils.expire(requestLoginIp, Constant.REQUEST_LOGIN_LIMIT_TIME);}if (loginCount > Constant.REQUEST_LOGIN_LIMIT_COUNT) {log.warn("IP:[".concat(ip).concat("]已超出限定次數"));throw new RuntimeException("時間段內已超出限定次數,請不要頻繁登錄!");}......} }
    • 測試與驗證


    三、Hash的應用場景:存儲用戶信息

    創建SpringBoot后臺服務程序,實現微信小程序登錄及JWT認證;
    通過Redis緩存記錄該用戶最后一次登錄時間及登錄累計次數。

    /*** 授權登錄接口實現類--增加redis緩存哈希表應用** @author zhuhuix*/ @Slf4j @Service @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class AuthServiceImpl implements AuthService {........// 將當前用戶信息與登錄時間寫入Redis緩存的哈希表// 以微信登錄用戶的openId作為哈希鍵值String key = authUserDto.getUserInfo().getOpenId();redisUtils.hashSet(key, "id", authUserDto.getUserInfo().getId());redisUtils.hashSet(key, "nickName", authUserDto.getUserInfo().getNickName());redisUtils.hashSet(key, "getAvatarUrl", authUserDto.getUserInfo().getAvatarUrl());redisUtils.hashSet(key, "lastLoginTime", Timestamp.valueOf(LocalDateTime.now()));// 讀取緩存中當前哈希值對應的用戶的登錄次數Long loginCount = 1L;Object obj = redisUtils.hashGet(key, "loginCount");if (obj != null) {loginCount += Long.valueOf(String.valueOf(obj));}// 累加后回寫到哈希表中redisUtils.hashSet(key, "loginCount", loginCount);...}
    • 測試與驗證

    四、List的應用場景:隊列實現

    • 創建SpringBoot上傳文件WebApi服務接口;
    • 通過Redis緩存隊列記錄最新10筆用戶上傳文件的信息。

    • 圖片上傳服務源碼中增加Redis隊列
    /*** 微信小程序CRM實現類:實現Redis隊列** @author zhuhuix*/ @Slf4j @AllArgsConstructor @Service @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class WxMiniCrmImpl implements WxMiniCrm {...@Override@Transactional(rollbackFor = Exception.class)public Result<CrmIndex> uploadCrmIndex(String json, String openId, String realName, MultipartFile multipartFile) {try {JSONObject jsonObject = JSONObject.parseObject(json);String createTime = jsonObject.getString("create");String employeeCode = jsonObject.getString("employeeCode");String customerCode = jsonObject.getString("customerCode");String customerName = jsonObject.getString("customerName");String type = jsonObject.getString("type");if (StringUtils.isEmpty(createTime) || StringUtils.isEmpty(employeeCode) || StringUtils.isEmpty(customerCode)|| StringUtils.isEmpty(customerName) || StringUtils.isEmpty(type)) {throw new RuntimeException("上傳信息中缺少關鍵資料");}UploadFile uploadFile = uploadFileTool.upload(openId, realName, multipartFile);if (uploadFile == null) {throw new RuntimeException("上傳文件失敗!");}CrmIndex crmIndex = new CrmIndex();DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");crmIndex.setCreateTime(Timestamp.valueOf(LocalDateTime.parse(createTime, dateTimeFormatter)));crmIndex.setEmployeeCode(employeeCode);crmIndex.setCustomerCode(customerCode);crmIndex.setCustomerName(customerName);crmIndex.setType(type);crmIndex.setJson(json);crmIndex.setOpenId(openId);crmIndex.setPath(uploadFile.getPath());// 將最新10條上傳的信息放入redis緩存if (redisUtils.size(Constant.REDIS_UPLOAD_QUEUE_NAME) >= Constant.REDIS_UPLOAD_QUEUE_COUNT) {log.warn(Constant.REDIS_UPLOAD_QUEUE_NAME.concat("隊列已滿,移除最舊上傳信息:") + redisUtils.rightPop(Constant.REDIS_UPLOAD_QUEUE_NAME));}log.info(Constant.REDIS_UPLOAD_QUEUE_NAME.concat("隊列增加上傳信息:").concat(crmIndex.toString()));redisUtils.leftPush(Constant.REDIS_UPLOAD_QUEUE_NAME, crmIndex);return new Result<CrmIndex>().ok(crmIndexRepository.save(crmIndex));} catch (JSONException ex) {throw new RuntimeException("json轉換失敗:" + ex.getMessage());}}... }

    文件上傳的原理與實現可參考該文章《SpringBoot實現微信小程序文件上傳的完整案例》

    • 測試與驗證

    • 微信小程序端
      – 前端將識別信息與圖片上傳至服務器

    • Redis緩存隊列
      – 隊列中只保存最新10條(數量可自行調整)信息.:

    五、Set的應用場景:自動去重

    • 創建SpringBoot添加客戶信息服務接口;
    • 通過Redis集合緩存客戶信息,要求自動去重,不得重復記錄。

    • 客戶實體類
    /*** CRM客戶信息** @author zhuhuix*/ @Entity @Getter @Setter @Table(name = "customer") public class Customer implements Serializable {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@NotNull(groups = Update.class)private Long id;@Column(name = "open_id")private String openId;/*** 客戶代碼*/@Column(name = "customer_code")private String customerCode;/*** 客戶名稱*/@Column(name = "customer_name")private String customerName;/*** 首字母*/@Column(name = "first_letter")private String firstLetter;/*** 創建時間*/@Column(name = "create_time")@CreationTimestampprivate Timestamp createTime;/*** 更新時間*/@Column(name = "update_time")@UpdateTimestampprivate Timestamp updateTime;@Overridepublic String toString() {return "Customer{" +"customerCode='" + customerCode + '\'' +", customerName='" + customerName + '\'' +'}';} }
    • 客戶信息WebApi
    @ApiOperation(value = "通過掃一掃功能上傳客戶信息")@PostMapping(value = "/crmScan/{openId}")public ResponseEntity crmScan(@RequestBody WxScanDto wxScanDto, @PathVariable String openId) {return ResponseEntity.ok(wxMiniCrm.wxScan(wxScanDto, openId));}
    • 記錄并緩存客戶信息實現類
    /*** 微信小程序CRM實現類** @author zhuhuix*/ @Slf4j @AllArgsConstructor @Service @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class WxMiniCrmImpl implements WxMiniCrm {private final UploadFileTool uploadFileTool;private final CrmIndexRepository crmIndexRepository;private final CustomerRepository customerRepository;private final UserService userService;private final RedisUtils redisUtils;...@Override@Transactional(rollbackFor = Exception.class)public Result<WxScanDto> wxScan(WxScanDto wxScanDto, String openId) {//微信掃一掃保存客戶信息if (Constant.SAVE_CUSTOMER_INFO.equals(wxScanDto.getScanType()) && wxScanDto.getJsonObject() != null) {try {Customer customer = JSONObject.parseObject(wxScanDto.getJsonObject().toJSONString(), Customer.class);Customer target = customerRepository.findByCustomerCodeAndOpenId(customer.getCustomerCode(), openId);if (target != null) {BeanUtils.copyProperties(customer, target, RepositoryUtil.getNullPropertyNames(customer));} else {target = customer;target.setOpenId(openId);}wxScanDto.setReturnObject(customerRepository.save(target));// 將用戶增加的客戶信息添加到redis集合中redisUtils.setAdd(openId.concat("_customer"),customer.toString());return new Result<WxScanDto>().ok(wxScanDto);} catch (JSONException ex) {throw new RuntimeException("json轉換失敗:" + ex.getMessage());}}return new Result<WxScanDto>().error("無法處理掃一掃功能");}}
    • 測試與驗證
  • 相同信息自動去重:通過swagger2進行接口測試,多次提交相同的客戶信息
    • Redis Desktop Manager驗證數據
      – 查看集合中的數據,實現自動去重
  • 不同集合之間的交集與差集:用戶1通過接口添加4個客戶

    –用戶2通過接口添加3個客戶

    – 獲取用戶1與用戶2相同及不同的客戶信息
  • /*** Redis測試* * @author zhuhuix*/ @SpringBootTest @Slf4j public class TestSet {@Testvoid test() {RedisUtils redisUtils = SpringContextHolder.getBean(RedisUtils.class);//獲取交集:相同客戶Set<Object> setInter=redisUtils.setInter("openId1_customer","openId2_customer");Iterator iterator = setInter.iterator();log.info("openId1_customer與openId2_customer相同的客戶為:");while(iterator.hasNext()){log.info(iterator.next().toString());}//獲取差集:不同客戶Set<Object> setDiff=redisUtils.setDifference("openId1_customer","openId2_customer");iterator = setDiff.iterator();log.info("openId1_customer與openId2_customer不同的客戶為:");while(iterator.hasNext()){log.warn(iterator.next().toString());}//獲取差集:不同客戶Set<Object> setDiff1=redisUtils.setDifference("openId2_customer","openId1_customer");iterator = setDiff1.iterator();log.info("openId2_customer與openId1_customer不同的客戶為:");while(iterator.hasNext()){log.warn(iterator.next().toString());}} }
    • 測試結果

    總結

    以上是生活随笔為你收集整理的Redis项目应用场景与实例汇总的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。