社区系统项目复盘-4

news2024/11/27 4:27:19

文章目录

      • Redis高性能存储
      • 什么是Redis?
      • 为什么使用Redis?
      • Spring是怎么整合Redis的?
      • Redis事务管理
      • 点赞
      • 关注
      • 优化登录模块

Redis高性能存储

使用redis实现了点赞、关注相关的功能,优化了登录模块。

什么是Redis?

Redis是一个开源的key-value存储系统,支持多种数据类型,包括string(字符串),list(链表),set(集合),zset(有序集合)和hash(哈希)。Redis操作都是原子性的(有一个失败则都失败)。Redis支持各种方式的排序。Redis数据可以缓存在内存中,也可以周期性的写入到磁盘中(即持久化操作),在此基础上实现了主从(master-slave)同步。

为什么使用Redis?

Redis将所有的数据都存放在内存中,所以读写速度很快。同时,Redis将内存中的数据以快照或日志的形式保存到硬盘上,以保证数据的安全性。

Spring是怎么整合Redis的?

第一步:引入依赖

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

第二步:对redis进行配置

  • 配置数据库参数
# RedisProperties
spring.redis.database=11
spring.redis.host=localhost
spring.redis.port=6379
  • 编写配置类,构造Spring Redis的核心组件RedisTemplate,这个组件是由Spring提供的
@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
        RedisTemplate<String,Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);

        // 设置key的序列化方式
        template.setKeySerializer(RedisSerializer.string());
        // 设置value的序列化方式
        template.setValueSerializer(RedisSerializer.json());
        // 设置hash的key的序列化方式
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置hash的value的序列化方式
        template.setHashValueSerializer(RedisSerializer.json());

        template.afterPropertiesSet();
        return template;
    }
}

第三步:访问redis的的不同数据类型

  • redisTemplate.opForValue()
  • redisTemplate.opForHash()
  • redisTemplate.opForList()
  • redisTemplate.opForSet()
  • redisTemplate.opForZset()

Redis事务管理

redis也是一个数据库,它也是支持事务的,redis事务管理的机制:当启用事务以后,再执行redis命令的时候,并不会立马执行命令,而是将命令放到一个队列里先存着,直到提交事务的时候才会将队列中的命令一次性发送给redis服务器一起执行。所以,redis使用事务的时候,不要在事务过程中做查询操作,因为查询不会立马显示结果,查询操作应当放在事务前或者事务后。

因为声明式事务只可以精确到方法,所以一般使用编程式事务,编程式事务示例如下:

// 编程式事务
    @Test
    public void testTransactional(){
        Object obj = redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                String redisKey = "test:tx";
                operations.multi();  // 启用事务

                operations.opsForSet().add(redisKey,"zhangsan");
                operations.opsForSet().add(redisKey,"lisi");
                operations.opsForSet().add(redisKey,"wangwu");
				  // 查询时是没有结果的。所以redis在管理事务的时候中间不要做查询,无效
                System.out.println(operations.opsForSet().members(redisKey));
                return operations.exec();  // 提交事务
            }
        });
        System.out.println(obj);
    }

点赞

点赞部分主要有两大块功能,第一块就是点赞,第二块就是收到的赞

主要显示页面:首页的帖子列表部分显示帖子的赞的数量;帖子详情上需要显示赞的数量以及点赞状态;个人主页上需要显示收到的赞的数量。

点赞:支持对帖子、评论点赞,第1次点赞,第2次取消点赞;需要显示点赞数量:对于首页点赞数量:统计帖子的点赞数量;对于详情页点赞数量:统计点赞数量,显示点赞状态。

详细步骤:点赞,首先调用点赞业务,查询点赞数量,当前点赞状态,~~根据点赞状态确定是否出发点赞事件(后面系统通知部分的功能),重新计算帖子分数(后面热帖的功能),~~最后返回响应。

注意⚠️:点赞部分的存储使用redis的set来实现,将点赞者的用户ID存到set中。

收到的赞:需要重构点赞功能,以用户为key,记录点赞数量,增加点赞数量使用increment(key),减少点赞数量使用decrement(key);开发个人主页,以用户为key,显示用户收到的点赞的数量。

详细步骤:业务层重构点赞方法,另外需要添加一个查询某个用户获得的赞的数量的业务层方法。开发个人主页时,需要显示的内容主要有:用户信息,获得点赞数量,关注数量,粉丝数量,是否已关注,下一部分实现关注相关功能。

注意⚠️:使用了redis事务管理,把点赞与记录点赞数量两个redis命令放在一个事务。
收获的赞的数量使用redis的String来存储,存储的值为整数类型。

在这里插入图片描述

关注

关注、取消关注

  • 需求:开发关注、取消关注功能;统计用户的关注数、粉丝数。实现个人首页显示关注数量,粉丝数量,是否已关注的功能。
  • 关键:若A关注了B,则A是B的Follower(粉丝),B是A的Followee(目标);关注的用户可以是用户、帖子、题目等,在实现时将这些目标抽象为实体【这一句比较重要,抽象化】

⚠️注意:

  • 关注、取关功能,也是需要使用redis事务管理的,因为需要同时更新存储关注的rediskey和存储粉丝的rediskey。
  • 对于关注或者粉丝的存储,采用的是redis的zset数据结构,score使用的是当前系统时间。
  • 关注、取关功能为异步请求

关注列表、粉丝列表

  • 需求:在个人主页,点击关注或者粉丝,会相应的显示关注列表和粉丝列表,分页显示。
  • 关键:
    • 业务层:查询某个用户关注的人,支持分页;查询某个用户的粉丝,支持分页。
    • 表现层:处理“查询关注的人”,“查询粉丝”请求。

⚠️注意:业务层查询的信息用map来存,因为列表中不只需要有用户的信息,还需要有关注的时间。主要步骤是:先通过Redis查出来userid集合,然后遍历该集合,从根据userid从user数据库中查用户信息;关注时间是通过Redis来查询的,score就是关注时间。

在这里插入图片描述

优化登录模块

主要使用Redis优化3个方面:存储验证码,存储用户登录凭证,缓存用户信息

为什么要使用redis进行优化呢?

  • 使用Redis存储验证码
    • 验证码需要频繁的访问与刷新,对性能要求比较高
    • 验证码不需要永久保存,通常在很短的时间后就会失效
    • 分布式部署时,存在Session共享的问题
  • 使用Redis存储登录凭证
    • 处理每次请求时,都要查询用户的登录凭证,访问的频率非常高
  • 使用Redis缓存用户信息
    • 处理每次请求时,都要根据凭证查询用户信息,访问的频率非常高

在这里插入图片描述

⚠️注意:

  • 生成验证码的时候,用户还没有登录,此时无法获得userid,无法通过userid构造验证码对应的rediskey。所以生成验证码时临时给客户端颁发一个代表验证码归属的字符串就可以,这个字符串使用cookie发给客户端,同时使用该字符串构造存储验证码的rediskey。
// 验证码的归属
String kaptchaOwner = CommunityUtil.generateUUID();
Cookie cookie = new Cookie("kaptchaOwner",kaptchaOwner);
cookie.setMaxAge(60);
cookie.setPath(contextPath);
response.addCookie(cookie);
// 将验证码存入Redis
String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner);
redisTemplate.opsForValue().set(redisKey,text,60, TimeUnit.SECONDS);
  • 登录时检查验证码,此时标识验证码归属的字符串通过cookie传过来,然后我们通过这个字符串从redis里获得验证码的正确值,然后再校验验证码是否正确。
//检查验证码
// String kaptcha = (String) session.getAttribute("kaptcha");
String kaptcha = null;
if(StringUtils.isNoneBlank(kaptchaOwner)){
	String redisKey = RedisKeyUtil.getKaptchaKey(kaptchaOwner);
	kaptcha = (String) redisTemplate.opsForValue().get(redisKey);
}
if(StringUtils.isBlank(kaptcha) || StringUtils.isBlank(code) || !kaptcha.equalsIgnoreCase(code)){
	model.addAttribute("codeMsg","验证码不正确!");
	return "/site/login";
}
  • 使用redis存取登录凭证,首先使用@Deprecated注解废弃LoginTicketMapper,修改登录时存储登录凭证的方式,修改退出登录时修改登录凭证状态的方式,修改查询登录凭证的方式。之前是将登录凭证存储在mysql数据库表中,现在把它存储到redis中里。
  • 查询user时,先尝试从缓存中取值,如果有,则直接返回值,如果没有,就从数据库中查找,将查找结果存到缓存中。数据变更时(激活的时候,修改密码的时候,上传头像的时候),需要更新数据库,这时候为了保持缓存和数据库中信息的一致性,可以有两种方法:一是同步更新缓存,二是直接将缓存中数据删掉,本项目采取方法二。
// 1.优先从缓存中取值
    private User getCache(int userId){
        String redisKey = RedisKeyUtil.getUserKey(userId);
        return (User) redisTemplate.opsForValue().get(redisKey);
    }
    // 2.取不到时初始化缓存数据
    private User initCache(int userId){
        User user = userMapper.selectById(userId);
        String redisKey = RedisKeyUtil.getUserKey(userId);
        redisTemplate.opsForValue().set(redisKey,user,3600, TimeUnit.SECONDS);
        return user;
    }
    // 3.数据变更时清除缓存数据
    private void clearCache(int userId){
        String redisKey = RedisKeyUtil.getUserKey(userId);
        redisTemplate.delete(redisKey);
    }

小结:点赞部分用了Set数据结构,点赞数量用的String数据结构。关注用的Zset数据结构。验证码的存取用的String数据结构。登录凭证的存取用的String数据结构。缓存用户信息用的String数据结构。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/47982.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]计算机毕业设计springboot基于vue的软件谷公共信息平台

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

力扣(LeetCode)895. 最大频率栈(C++)

设计 ①维护最大频率&#xff0c;②维护每个数的出现次数&#xff0c;③维护出现次数对应的栈。 压栈时&#xff0c;新数压入出现次数对应的栈&#xff0c;每次压入新数&#xff0c;维护最大频率(所有出现次数中的最大出现次数)。 弹栈时&#xff0c;找最大频率对应的栈&…

RealEvo许可证协议

一直使用RealEvo V4.0.0版&#xff0c;今天因license到期&#xff0c;索性一同安装下新版的IDE。 当前最新RealEvo IDE版本为 V5.0.5&#xff0c;V5.0.0~V5.0.3版本存在一些bug&#xff0c;建议更新。 SylixOS 许可信息如下&#xff08;开源版本&#xff09; SylixOS嵌入式实…

【毕业设计】前后端分离——实现登录注册功能

&#x1f308;据说&#xff0c;看我文章时 关注、点赞、收藏 的 帅哥美女们 心情都会不自觉的好起来。 前言&#xff1a; &#x1f9e1;作者简介&#xff1a;大家好我是 user_from_future &#xff0c;意思是 “ 来自未来的用户 ” &#xff0c;寓意着未来的自己一定很棒~ ✨个…

Word控件Spire.Doc 【图像形状】教程(8): 如何借助C#/VB.NET在 Word 中插入艺术字

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

基于51单片机的智能蓝牙路灯街灯控制系统proteus仿真原理图PCB

功能&#xff1a; 0.本系统采用STC89C52作为单片机 1.液晶实时显示时间/环境光强/工作模式 2.每隔5s向蓝牙串口发送一次信息 3.支持路灯故障检测 4.工作时间18~24时&#xff0c;两个路灯同时点亮&#xff0c;24时以后&#xff0c;B路灯关闭&#xff0c;若检测到由物体通过&…

【Kafka】Kafka的重复消费和消息丢失问题

文章目录前言一、重复消费1.1 重复消费出现的场景1.1.1 Consumer消费过程中&#xff0c;进程挂掉/异常退出1.1.2 消费者消费时间过长1.2 重复消费解决方案1.2.1 针对于消费端挂掉等原因造成的重复消费问题1.2.2 针对于Consumer消费时间过长带来的重复消费问题二、消息丢失2.1 生…

Multipass,多平台本地轻量级Linux体验!

Multipass 是由Ubuntu官方提供&#xff0c;在Linux&#xff0c;MacOS和Windows上快速生成 Ubuntu虚拟机 的工具。它提供了一个简单但功能强大的CLI&#xff0c;可让我们在本地快速进入Ubuntu系统环境并使用Linux命令&#xff0c;亦可以在本地计算机创建自己的迷你型云服务器。总…

zabbix监控网络连接状态

目录 一、环境准备 二、网络连接状态介绍 三、自定义监控key 四、给主机添加监控项 一、环境准备 1、搭建zabbix基础环境 zabbix基础环境部署参照&#xff1a;zabbix基础环境部署_桂安俊kylinOS的博客-CSDN博客 2、给web1安装nginx环境&#xff0c;并加载status模块 以…

SpringCloud学习笔记 - 链路监控 - SpringCloud Sleuth

1. Sleuth简介 在微服务框架中&#xff0c;一个由客户端发起的请求&#xff0c;在后端系统中会调用多个不同的的服务节点&#xff0c;来协同产生最后的响应结果&#xff0c;因此每一个前端请求都会形成一条复杂的分布式服务调用链路&#xff0c;链路中的任何一环出现高延时或错…

信号量Semaphore详解

前言 大家应该都用过synchronized 关键字加锁&#xff0c;用来保证某个时刻只允许一个线程运行。那么如果控制某个时刻允许指定数量的线程执行&#xff0c;有什么好的办法呢? 答案就是JUC提供的信号量Semaphore。 介绍和使用 Semaphore&#xff08;信号量&#xff09;可以用…

iwebsec靶场 SQL注入漏洞通关笔记10- 双重url编码绕过

系列文章目录 iwebsec靶场 SQL注入漏洞通关笔记1- 数字型注入_mooyuan的博客-CSDN博客 iwebsec靶场 SQL注入漏洞通关笔记2- 字符型注入&#xff08;宽字节注入&#xff09;_mooyuan的博客-CSDN博客 iwebsec靶场 SQL注入漏洞通关笔记3- bool注入&#xff08;布尔型盲注&#…

VF01销售开票发票金额控制增强

实施隐式增强 全部代码如下&#xff1a; method IF_EX_BADI_SD_BILLING~INVOICE_DOCUMENT_CHECK. CALL FUNCTION ‘SIPT_DOC_CHECK_SD’ EXPORTING it_xvbrk fxvbrk it_xvbrp fxvbrp it_xkomv fxkomv it_xvbpa fxvbpa IMPORTING ev_bad_data fbad_data. “”“”“”“…

【LeetCode每日一题】——171.Excel 表列序号

文章目录一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【解题思路】七【题目提示】八【时间频度】九【代码实现】十【提交结果】一【题目类别】 字符串 二【题目难度】 简单 三【题目编号】 171.Excel 表列序号 四【题目描述】 给你一个字…

SecXOps 技术发展趋势

可以预见&#xff0c;安全智能分析技术的发展&#xff0c;将全面提升网络安全 关键应用场景下威胁检测的效果&#xff0c;推动安全分析从基础级、领先级&#xff0c;向卓越级演进。根据 Gartner 2021 年十大数据和分 析技术趋势&#xff0c;XOps 的目标是利用 DevOps 最佳实践实…

计算机网络性能指标——时延,时延带宽积,RTT和利用率

时延 时延&#xff1a;数据&#xff08;报文、分组、比特流&#xff09;从网络的一端传送到另一端所需要的时间。也叫延迟或迟延&#xff0c;单位是s。 时延包括&#xff1a;发送时延&#xff08;传输时延&#xff09;,传播时延&#xff0c;排队时延&#xff0c;处理时延。 高…

2022年最新安徽食品安全管理员模拟试题及答案

百分百题库提供食品安全管理员考试试题、食品安全管理员考试预测题、食品安全管理员考试真题、食品安全管理员证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 1.引起副溶血弧菌食物中毒的主要食品是&#xff1a; A.罐头食品…

公司新来一个同事,把网关系统设计的炉火纯青,万能通用,稳的一批。。

本文准备围绕七个点来讲网关&#xff0c;分别是网关的基本概念、网关设计思路、网关设计重点、流量网关、业务网关、常见网关对比&#xff0c;对基础概念熟悉的朋友可以根据目录查看自己感兴趣的部分。 什么是网关 网关&#xff0c;很多地方将网关比如成门&#xff0c; 没什么…

操作系统学习(九)死锁

目录 学习建议&#xff1a; 基本内容&#xff1a; 一、死锁的形成&#xff1a; 二、死锁的必要条件&#xff1a; 三、资源分配图&#xff1a; 四、解决死锁问题的几个策略&#xff1a; 五、死锁的防止&#xff1a; 1.互斥条件&#xff1a; 2.占有并等待资源&#xff1a…

[NCTF2019]SQLi

进来就有个弹窗 甚至给了sql语句 sqlquery : select * from users where username and passwd 先扫一下目录&#xff0c;发现有个robots.txt 提示有个hint.txt $black_list "/limit|by|substr|mid|,|admin|benchmark|like|or|char|union|substring|select|greatest|%00…