谁去哪个店铺发布了那些内容信息(图片、文字、标题)以及后台内容信息(点赞数、评论数、发布时间、修改时间)这里图片存入的是地址,在添加图片还未发布时,图片就已经上传并返回地址,发布时携带图片地址一起上传
一个用户同一个笔记只能点一个赞,再点一次则取消
因此需要判断当前博文有没有被该登录用户点过赞,给博文添加一个isLike
字段,在查询博文时,也根据用户id,查询用户在查询时判断此用户是否给其点过赞,为其赋值
查询用户是否为其博文点赞方式:
显示按时间点赞的前5名用户
涉及排行榜,要想到redis集合中 进行有序存储的SortedSet
(list虽然也支持排序,但元素不唯一,且链表查找较慢),使用时间戳作为score,由于sortedSet是降序排列,时间戳小的就会靠前,正好符合题意。要将原来储存博文点赞信息的set集合改为sortedSet集合,由于储存的信息都是用户id,所以还有去数据库查询用户的基本信息(头像、昵称等)
但sortedSet 没有判断元素是否存在的命令,只能通过查询分数来判断是否为null zScore key element
, zRange key 0 4
按照分数(这里存入的是时间戳)查询前5名点赞用户的id
问题:
虽然从redis中获取的是按照时间戳
由小到大,但数据库查询结果是按照用户id
由小到大 ,数据库将参数自动进行排序,不符合业务规则
此用户可以关注很多其他用户,其他很多用户也可以关注此用户,因此是多对多关系。采用中间表进行连接
关注:将关注的用户和被关注的用户插入表中
取消关注:将对应数据删除
利用set的交集功能 ,A关注的博主id存入A的set集合中,B关注的博主id存入B的set集合中,最后将A和B set中内容的求交集即为共同关注内容
用户发表博文时,将内容投送给粉丝
Timeline
:不做内容筛选,简单的按照内容发布时间排序。例如朋友圈:只要有好友无论内容是否感兴趣,就会进行推送
智能排序
: 通过智能算法屏蔽掉用户不感兴趣的内容,根据用户喜好进行推送
项目中使用 Timeline
拉模式
(读扩散):被关注的用户将博文id按时间顺序发送到自己的发件箱
中(被动),粉丝们在读取所有关注者动态时,会从各个被关注者的发件箱中拉取
到自己的收件箱,并按时间进行排序。就像点多家餐,自己要去挨家去取
推模式
(写扩散):被关注者发送博文时,将博文id推送到各个粉丝的收件箱中(主动),自己不做保留,没有发件箱。粉丝的收件箱将各个消息按时间进行排序,根据id去数据库中查找,转换成为对应博文。就像点多家餐,等待多个外卖送到家中
推拉模式
:将不同的用户采取不同的策略。例如粉丝较少,采用推模式可以较少耗时,又不会大量备份;粉丝数量较多,采用拉模式,可以避免大量消息重复,又可以防止僵尸粉耗费资源(因为虽然关注但不查看,就没必要放在他的收件箱,想要查看时进行拉取即可)
问题:
使用 list
or SortedSet
?二者都可以进行排序,从而进行分页
传统分页
list只能根据角标进行查询,而数据可能不断变化,导致角标经常发生变化
例:插入 C,B,A(越新的数据越靠前) , 每次分页查询前两条数据即C,B ;查询下一页时,数据新增D ,查询出的数据变为 D,C。导致角标对应的数据发生变化,数据混乱
每次记录查询的最后一条,下次查询从最后一条往后去查询。这样查询需要获取值的内容,并使用值去排序
而
SortedSet
中,正好有一个 可以按照值的范围去查找 zrange min max count
,图中的值可为时间戳,不断增大
使用sortedSet
按照角标方式 如果按照升序排列,时间戳为score,每次读取从旧到新,就不会导致排名发生变化,但不符合业务要求从新到就旧
reids使用Geo
进行地理位置处理
存储地理位置信息,进行地理位置计算
常用命令:
6.2版本出现
前端 传递 定位的经纬度(x,y),商家类型,距离范围
按距离范围搜索功能是由redis的GEO数据结构自动完成的,在注册商家时,要将商家编号对应的位置信息添加在redis中 。为了方便查询分组将他们按照类型分为一组,即同一个key
由于附近店铺搜索的 GeoSearch 命令出现在redis 6.2版本之后,redis场景启动器配置的版本过低,因此需要移除旧版本,换入新版本
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
<exclusions>
<exclusion>
<artifactId>spring-data-redisartifactId>
<groupId>org.springframework.datagroupId>
exclusion>
<exclusion>
<artifactId>lettuce-coreartifactId>
<groupId>io.lettucegroupId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.springframework.datagroupId>
<artifactId>spring-data-redisartifactId>
<version>2.6.2version>
dependency>
<dependency>
<groupId>io.lettucegroupId>
<artifactId>lettuce-coreartifactId>
<version>6.1.6.RELEASEversion>
dependency>
采用数据表形式太重
而采用位图思想,每一天有两种可能(签到或没有签到),所以使用二进制 0 1 表示。一个月最多有31天,每个人只需要31个bit,不到4B的数据就可以记录一个月的签到情况
redis使用BitMap
来实现
常用命令:
setBit 【key】【要设置第几位】【置为 1 or 0】 :将key的第几个位置存入一个 0 或 1 。默认为0 (常用于签到
)
getBit 【key】【要获取第几位】:获取key的第几位的bit值 (判断哪天有没有签到
)
BitCount 【key】:统计key中1的个数 (查看一个月签到了多少天
)
BitField 【key】【操作类型 GET】【是否有符号 i:有符号 u:无符号】【读取位数】【从哪里开始读取】:常用无符号的一次读取多个位数的bit位 (常用获取具体的签到结果
)
BitOp【key】:将bitMap的结果记性运算
统计连续签到的天数即 从当天数,连续为1的bit个数
一个很长的二进制向量和一系列随机映射函数。主要用于判断一个元素是否在一个集合中。
根据 :两个哈希值相同但原始值不一定相同(哈希碰撞),但原始值相同哈希值一定相同
。将key转为哈希值,并将值对应bit的位置 置为1,即代表key存在。查询时,将key转为hash值,在去bitMap的对应位置比对
,判断是否为1,若为0则代表数据中一定不存在,进行拦截 。 若hash数字过长,可除bitMap设定的最大值(会增大误差),确保所有hash结果都能找到对应的bitMap中bit位。
特点:
可用于拦截 如:缓存穿透;去重;,但存在小概率误差
相关链接
问题:
getBit
只能获取某一天一个数据,要获取多个数据只能使用bitFIeld
指定起始位置(本月第一天)与获取个数(即当日所在的位置),获取多个数据,但会把二进制转为十进制>>>
,使得下一位与1进行与运算,如此循环uv
即 Unique Visitor 独立访客量。即每天每个人无论访问多少次该网站,都只会被记录一次
pv
即 Page View 页面访问量:只要有一访问,无论是否是一个人多次访问,,只要访问一次就记录一次。用户衡量网站流量
uv统计要判断次数的同时,还要判定身份,确保是不同的人才会进行+1。如果直接写入,将会导致非常大的数据量
一种概率统计算法,基于String数据结构实现 。用户确定数据量非常大的集合基数,而不需要存储其所有值。最大亮点无论多么大的数据量,内存占用永远小于16K
,但是有小于0.81%
误差
常用命令:
合并
。例如 每天统计访问用户数,最后合并可求出一个月的有多少个访问的用户数黑马点评项目结束