• a、什么是session

session是一种会话技术,我们知道http是无状态协议的,就是这次连接传输数据后,下次连接服务器是不知道这次的请求是谁的,因此我们要做一个标记,让服务器知道每次请求是哪个(客户端)浏览器发出的,就是请求的时候服务器会创建一个session把session的值保存在服务器,把sessionID返回给浏览器,请求的时候把sessionID放在请求头中,这样服务器解析之后就能发现是哪个浏览器发来的请求

  • b、session存放在什么地方,会引起什么问题

session是存在服务器的,只是把sessionID返回给浏览器。这样我们把浏览器关掉,session也不会实现,但是只是丢失了sessionID,这样也是访问不到的。

  • c、session的工作原理

session是由服务器创建的,存放在服务器中,把sessionID返回给浏览器,请求的时候,每次请求把sessionID就到请求头中,服务器解析以后就知道是哪个浏览器

  • e、分布式session是什么

我们知道session是保存在服务器的,这样当我们的项目做了负载均衡以后,如果在session中存了数据,那么就有可能有有些项目取不到session中的数据,这就是分布式session问题

通常我们在开发后台管理系统时,会使用 Session 来保存用户的会话(登录)状态,这些 Session 信息会被保存在服务器端,但这只适用于单系统应用,如果是分布式系统此模式将不再适用。

例如用户一的 Session 信息被存储在服务器一,但第二次访问时用户一被分配到服务器二,这个时候服务器并没有用户一的 Session 信息,就会出现需要重复登录的问题,问题在于分布式系统每次会把请求随机分配到不同的服务器。

分布式系统单独存储 Session 流程图:

因此,我们需要借助 Redis 对这些 Session 信息进行统一的存储和管理,这样无论请求发送到那台服务器,服务器都会去同一个 Redis 获取相关的 Session 信息,这样就解决了分布式系统下 Session 存储的问题。

分布式系统使用同一个 Redis 存储 Session 流程图:


  • Redis 用作缓存,其特点之一就是数据可以丢,只需要保证其响应急速,性能较高!
  • 但是如果把 Redis 做数据库:数据绝对不能丢的,所以除了保证其速度之外,还必须保证其持久性,数据一定不可以丢失

而我们知道 Redis 处于内存,内存数据掉电易失!所以如果想要使用 Redis 作为数据库,必须要保证其持久性

只要是存储层,为了保证数据安全,都会有如下两个通用的功能:

  • 快照/副本:记录某一时刻数据库中所有的正确数据状况。可以保存在本地主机,也可以拷贝到另一台远程主机,一旦出现断电,甚至服务器瘫痪,也可以根据快照恢复某一时刻的正常数据
  • 日志:用户发生增删改的时候,所有的操作都会记录到一个日志文件。如果周一数据正常,周二系统上线新功能出现一个致命错误,造成大量资金损失,此时可以将系统紧急停服,根据日志将数据回滚到一个正常状态

项目中点赞、关注、验证码这几个功能都是把redis当做数据库使用的,没有当做缓存使用,不会有缓存和数据库的一致性问题。

缓存点赞和关注:

(1)首页上会显示被点赞了多少次,所以Redis缓存用户点赞数量,用String类型,以用户ID为key,点赞时,自增,取消赞时,自减;用户点赞key的设计了这个没啥,就是一个用户id就好了存储的value也就是数量就好了,like:user:userId -> int,这个操作的设计是为了后面发送系统消息的需求提供的之后再讲业务逻辑。

(2)点赞可以对帖子点赞,也可以对帖子的评论点赞,缓存实体点赞数,用set类型,为了能看对谁点的赞,以点赞对象为key,用户给实体点赞时添加进列表,取消赞时则移除;

首先这是个实体点赞操作部署关注操作对吧,所以key里面要有like字段,

然后点赞操作我们需要知道这是个帖子啊还是评论啊,还是回复啊所以我们还需要实体的类型是吧,

再者就是这个实体的id了。然后这个点赞是我点的吧需要我的id对吧。

所以key为like:entity:entityType:entityId这样设计还能提供拓展性如果以后提供了更多的点赞种类都能使用比如我还想增加一个给用户直接点赞的需求那么只需要type+1就好了。
然后巧妙的地方来了value我选用的是set(userid),为了能看谁点的赞。因为我们需要考虑到这个用户有可能是点错了啦要取消点赞哒,所以存储set可以判断这个用户有没有点过赞然后才能进行操作,而且set还能获得点赞的数量这样岂不美哉。

(3)缓存粉丝列表,也就是关注操作,使用zset,存入粉丝的id和关注的时间戳,使用zCard获得粉丝数量。利用reverseRange的时间戳反向排序,按关注时间加载粉丝列表。

key设计要分为两个一个是某个实体(用户)关注的实体(用户)列表,一个是一个实体(用户)被关注的实体(用户)列表,说白了就是我的关注和我的粉丝
// 某个用户关注的实体
// followee:userId:entityType -> zset(entityId,now)
// userId -> 某个关注别人的关注者id
// entityType -> 关注的类型,可以是帖子可以是人等待
// value是zset(entityId,now) 是一个有序集合以时间为score,以实体id为值
// 某个实体拥有的粉丝
// follower:entityType:entityId -> zset(userId,now)
// entityType -> 实体类型可以是用户可以是帖子等等
// entityId -> 这个实体的id
// 有了这两个参数可以唯一的表示某个实体,比如说如果这个实体是人那么entityType就是人entityId就是userId如果这个实体是帖子那么entityType就是帖子entityId就是帖子id
// value是zset(userId,now)是一个有序集合,集合中值是userId表示是哪个用户关注了这个实体

点赞 具体实现:

存在redis里就像操作map里,存数据取数据是面向key编程的,所以为了让key反复复用,最好给redis写一个工具专门生成key.,写一个工具类 RedisKeyUtil ,帖子和评论都统称为实体,我们要完成的就是存实体的赞的key,写 getEntityLikeKey 方法,传入 entityType, entityId (实体类型和实体ID)返回某个实体(帖子或回复)的赞的key值 。key由多个单词拼接而成,中间采用冒号隔开,有的单词是固定的,有些单词是动态的,设计方法如下所示:

public class RedisKeyUtil {private static final String SPLIT = ":";private static final String PREFIX_ENTITY_LIKE = "like:entity";// 某个实体的赞// like:entity:entityType:entityId -> set(userId)用一个集合存赞,谁给这个实体点的赞就存上public static String getEntityLikeKey(int entityType, int entityId) {return PREFIX_ENTITY_LIKE + SPLIT + entityType + SPLIT + entityId;}
}

set(userId)用一个集合存赞,谁给这个实体点的赞就存上。

① 在帖子详情页面对帖子内容点赞, entityType=0,对回复点赞, entityType=1,通过 /like 映射传递给 LikeController 层中的 like 方法。

②like 方法通过调用 likeService 层的 like 进行点赞功能,然后再依次调用 findEntityLikeCount,findEntityLikeStatus 方法查询该帖子的点赞数量,查询当前登录用户的点赞状态。

③ likeService 层的 like 方法首先判断是否已经点过赞了,如果没有,就在Redis中该帖子key对应的set中加入点赞者的userId,并且对该帖子用户的赞的总数加一。如果已经赞过则移除UserId,并且对该帖子用户的赞的总数减一。

④ 将点赞的数量和状态封装进map,通过json字符串返回。在浏览器中显示。

收到的赞

前提:在 util 的 RedisKeyUtil 工具类中写 getUserLikeKey 方法,返回某个用户的赞总数的key。

  1. 点击个人主页或者点击其他用户头像进入他人个人主页,映射到 UserController层(/user)的 /profile/{userId} 。首先判断该用户存不存在。
  2. 然后根据该用户的 id 调用 likeService.findUserLikeCount 方法返回点赞数量。findUserLikeCount 方法首先根据userId 调用 getUserLikeKey 方法,返回该用户的赞总数的key。然后使用 redisTemplate 查询key对应的值返回给点赞数量。
  3. 将点赞数量加入model中返回浏览器显示。

关注

实现关注和取关的操作,还要统计用户的关注数和粉丝数。Follower粉丝,Followee目标。依旧用Redis实现。

还是先从key开始,在RedisKeyUtil里声明两个前缀,也就是要存两份数据,在这里拼两份用zset(entityId,now)以当前时间作为分数来统计

1.在他人个人主页点击关注,根据 profile.js 异步请求映射到 FollowController 层的 /follow。传入entityType 和 entityId。然后调用 followService.follow 方法进行关注。

2.followService.follow 方法首先根据 userId, entityType, entityId 获取到前提中的两个key,开启事务,对当前登录用户的关注的key对应的 ZSet 加入 entityId。被关注用户的粉丝的key对应的 ZSet 加入 userId(Redis存的是有序Set,score采用当前时间插入)。

4.返回关注成功Json。

5.此时按钮显示已关注,若再次点击则映射到 /unfollow。调用 followService.unfollow 方法取消关注。与第2步骤逻辑基本相同,分别减一

8.redis解决分布式session问题 、redis在项目中难点相关推荐

  1. 170222、使用Spring Session和Redis解决分布式Session跨域共享问题

    使用Spring Session和Redis解决分布式Session跨域共享问题 原创 2017-02-27 徐刘根 Java后端技术 前言 对于分布式使用Nginx+Tomcat实现负载均衡,最常用 ...

  2. SpringSession+redis解决分布式session不一致性问题

    七.案例实战:SpringSession+redis解决分布式session不一致性问题 步骤1:加入SpringSession.redis的依赖包 <dependency><gro ...

  3. 使用Spring Session和Redis解决分布式Session跨域共享问题

    大家可以关注一下公众号"Java架构师秘籍" 前言 对于分布式使用Nginx+Tomcat实现负载均衡,最常用的均衡算法有IP_Hash.轮训.根据权重.随机等.不管对于哪一种负载 ...

  4. 场景应用:利用Redis实现分布式Session

    文章目录 原理:Redis实现分布式Session web开发session 分布式session同步问题 分布式session解决方案 实战:Redis实现分布式Session 技术栈:Spring ...

  5. Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session框架

    Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session import tornado.ioloopimport tornado.webfrom myhash ...

  6. Spring Session + Redis实现分布式Session共享

    2019独角兽企业重金招聘Python工程师标准>>> 通常情况下,Tomcat.Jetty等Servlet容器,会默认将Session保存在内存中.如果是单个服务器实例的应用,将S ...

  7. 如何利用Redis实现分布式Session?

    在web开发中,我们会把用户的登录信息存储在「session」里.而session是依赖于「cookie」的,即服务器创建session时会给它分配一个唯一的ID,并且在响应时创建一个cookie用于 ...

  8. springboot+redis实现分布式session共享

    官方文档,它是spring session项目的redis相关的一个子文档:https://docs.spring.io/spring-session/docs/2.0.0.BUILD-SNAPSHO ...

  9. Redis实现分布式Session管理

    管理机制 redis的session管理是利用spring提供的session管理解决方案,将一个应用session交给Redis存储,整个应用中所有session的请求都会去redis中获取对应的s ...

最新文章

  1. Shell 文本操作利器收集
  2. 牛客网【每日一题】4月30日题目精讲 换个角度思考
  3. python selenium T3
  4. 如何把握网络工程师的“钱”途,专访文字。
  5. 有前途的程序员的14个习惯,你有几个?
  6. java Future FutureTask 并发操作
  7. Python 学习记录(1)对象命名导致的问题
  8. python计算信息增益_利用Python提取ABAQUS的计算结果(ODB)信息、体积、应变等变化(一)...
  9. Rust : channel、多线程与 CTP相关机制的模拟
  10. Linux ab 压力测试工具
  11. 查看游戏服务器ip地址网站,查看游戏服务器IP地址
  12. Kotlin相关博客资源
  13. html穿越火线游戏代码,CF代码大全.doc
  14. 【uni-app】uniapp项目优化方式及建议
  15. HTML、HTTP、Web综合面试题(三)
  16. 安卓局域网外实现木马监听
  17. 快慢指针判断链表中是否存在环以及查找环的起始位置
  18. 【01Studio MaixPy AI K210】15.人脸识别
  19. 2017十大网络黑客攻击事件丨阿里云河南
  20. WINDOWS时间服务启动失败的原因

热门文章

  1. java synthetic_synthetic
  2. Synthetic合成方法学习
  3. MySQL FULLTEXT全文索引
  4. Jenkins 设置中文显示方式
  5. 苹果 App Store 开始支持隐藏上架应用:只能通过链接下载
  6. vlc android局域网rtsp,基于Rtsp推流,实现局域网无纸化会议直播
  7. 基于多传感器的温湿度检测系统
  8. 沙盒勇者服务器维护,沙盒勇者新手攻略 新手入门少走弯路[多图]
  9. 传智黑马前端从基础班到就业班视频+资料(最新分享)
  10. Linux的super super super easy教程 | vim文本编辑器 1