4.1 Redis入门
Redis用来提高程序的性能。对性能要求比较高的功能可以使用Redis进行开发。
原来NoSql指的是not only sql。
如果按照快照进行存储,读取的时候,恢复也会比较快,但是缺点是,一下子将大量数据写到硬盘上,会造成阻塞,其他的业务请求需要暂时停下。可以隔几个小时进行一次。
如果按照日志的形式将数据保存到硬盘上,就是将数据一条一条地保存到硬盘上,可以保证实时性,但是由于是逐条记录,因此数据量比较大,占用硬盘资源比较多,在恢复的时候耗用的时间比较长。
Redis就学那几种数据类型就可以了,只需要会使用就行。使用各种命令就可以啦。
加入到环境变量中后直接就可以使用了,在终端 使用:
常用命令:它默认有16个数据库,使用select 1使用第一个数据库,select 2使用第二个数据库。
flushdb:数据库中的内容全部被删除。
在关系型数据库中连个单词中间使用_,但是在redis中使用:分开两个单词。[][]这样标识的表示可以省略不写。
set test:count 1 //value是字符串的形式。
get test:count
incr test:count//增加
decr test:count//减少
哈希类型
hset test:user id 1
hset test:user username 张三
hget test:user id
hget test:user username
列表展示
这一部分比较灵活
横向容器,支持从左装(取)以及右边装(取),可以呈现出队列和栈的效果。
lpush test:ids 101 102 103
len test:ids
lindex test:ids 0//查看索引为0 的数据。
lindex test:ids 2
lrange test:ids 0 2 //查看某一个范围中的数据
rpop test:ids
rpop test:ids
rpop test:ids
列表是有序的,集合是没有顺序的。集合中的内容是不能重复的。
接下来是集合:
sadd test:teachers aaa bbb ccc ddd eee
scard test:teachers //统计集合中的元素
spop teachers从集合中随机弹出一个元素
spop test:teachers//
这个命令一般可以用来实现抽奖
smembers test:teachers
//查看集合中剩下的元素
接下来展示有序的集合 :
给每一个存的数加上了一个分数,按照分数进行排序。
zadd test:students 分数 元素
zadd test:students 1 aaa 2 bbb 3 ccc
zcard test:students //统计数量
z score test:students ccc//查询cc的分数
zrank test:students ccc
查询排名,默认从小到大
zrange test:students 0 2
//取0-2左闭右闭
全局的命令:
keys :查询当前的库里一共有多少个key。
keys test //查询当前库里使用test开头的key一共有多少个。
type test:user//查看这个key对应值的类型
exists test:user查询存不存在
1表示存在
del test:user 删除这个key
exists test:user
//设置某一个key 的过期时间。
比如登录功能的验证码只需要存储大约一分钟即可。
expire test:students 10(seconds)
keys *//过一段时间按查询这个key还在不在。
可以发现超时之后就不见了。
4.7 Spring整合Redis
在引入包的时候,可以不用写版本。这里的包是指spirng整合的包。
配置数据库 :
RedisAutoConfiguration
这是springBoot对Redis进行自送配置使用的类。配的是RedisProperties.
这里配置的key是Object类型的,并不好用,因此我们不使用这个。需要重新进行 配置,不使用springBoot这个。
我们配置的时候面向的类是:
ReidsProperties。
这三个参数一定要自己进行配置。
template 有了工厂之后就具备了访问数据库的能力。
配置template主要配的是序列化的方式,我们写的是java程序,得到的是java类型的数据,但是最后需要存到Redis数据库中,因此需要指定一种序列化的方式。也就是数据转换的方式。Redis是key-value的存储方式,因此我们需要分别 指定他们的序列化方式。hash的 value比较特殊,因此我们需要指定他的key value的序列化方式。
接下来,编写配置类:
弄完所有的配置之后,需要触发一下,进行生效。
接下来开始展示通过RedisTemplate来访问Redis。
测试:
哪里需要访问Redis就将RedisTemplate注入到哪里去。
先检查一下这个库里面有没有其他的东西。发现啥也没有。
公共命令功能展示:
创建访问Redis的对象的时候就将key传进来。利用这个对象就可以反复访问同一个key。
简化方案,避免每次都传入key。
Redis事务:
只有关系型数据库才严格满足ACID这四个原则,Redis数据库并不满足这个原则。
比较简单的机制:
将命令放在某个队列中,一直等到事务提交之后才会一股脑执行队列中的所有的命令。
事务中的命令不会立刻执行,而是在提交的时候进行统一批量的执行,因此不要在事务中进行查询的操作(这个操做并不会立即返回结果),在事务之前进行,或者在事务执行之后查询。
我们一般使用编程式事务,声明式事务稚嫩更精确到某个方法。整个方法内部不能进行查询。只用编程式事务。
operations.multi()启用事务
operations.exec()提交事务。
前三个数字表示每一个数据影响的行数,后面的中括号表示当前列表里面的元素。
4.10 点赞
我们这里统计的并不是一个整数,也就是赞的数量,而是userId,到时候使用scard进行数量的统计即可。不仅可以知道是谁给点赞,还能知道点赞的个数。
由于这个功能比较简单,因此我们不再写数据访问层,直接写业务层。
查询实体的点赞数量,这些都应该在服务层计算好,表现层直接就使用了。
关于确定某人的点赞状态,我们不是使用布尔值来确定是不是点赞了,而是使用整型类确定,具备扩展性,可以点彩,或者超赞。
点赞是异步请求,只更新数据,但是不刷新页面。
this表示当前的节点,也就是当前的超链接。传入这个参数是为了区分当前点击的时哪一个 赞,因为当前页面有三个位置可以点赞。
那么返回的赞状态以及点赞的数量应该如何进行显示呢??
套上标签就能够识别了,然后对标签的内容进行更改。
第一个参数代表超链接,但是这个链接我们将其当成按钮来使用了。
通过
btn可以得到下一级的子标签b以及i。
ajax代码:
出现错误的时候应该首先检查服务端代码有没有出现问题,然后再检查前端的页面上有没有出现问题。
还有一些问题,页面必须出发才能正确显示。这一点需要进行纠正。
然后查看一下Redis里面数据有没有正确显示。
接下来开始对页面上面赞的显示进行处理。
在homeController中添加新的功能,查询赞的数量。
在帖子的详情页面上进行处理。
但是要在点赞状态那里进行一个判断。要不然会出错,压根没有user。
添加一个判断:
如此分别处理帖子,评论和回复。
4.13 我收到的赞
增加点赞的功能:
同一个like方法中需要进行两个操作,得保证一致性。
注意了,我们这里选择再传递一个参数(在页面上可以很方便得到),而不是将实体的作者传递过来,而不是通过查询数据库获得,因为我们本身就是为了避免查找数据库。
查询的这一行一定要放在事务之外。
以下就是重构的点赞的代码:
添加一个查询用户被赞多少次的代码:
接下来重构表现层和业务层的逻辑以及页面展示,比较简单了。在页面上为js方法增加一个参数。
以上添加只是为了点赞的时候对用户的点赞量进行累加,累加之后的结果是体现在用户的个人主页上面的。
个人主页显示的是每一个用户的主页,随便一个人都能查询别人的个人主页。
开始要进行一个查询,避免有人进行恶意查询,反复去查。
常量拼变量,记得加上双竖线。
帖子列表中的每一个帖子头像都会链接到相关的用户。
详情页面以及私信的页面也是这样,都应该在头像上面加上个人主页的链接。
【自行修改】
删除之前的点赞数据,为啥呢??不明白。。。
4.16 关注、取消关注
关注这个功能比较高频,我们将这个功能存储在Redis中。提高性能。
功能:关注,取关,增加数据
关注的代码逻辑:
取关的逻辑:
关注:
只演示如何去关注一个人,但是所有的关注功能基本上都是这样。
我们可以获取当前按钮的上一个节点来获得userId。
数据的显示:
登录用户不能是自己:没有登陆的话也没有允许登录的操作。
前端的相关知识记住就好了,不用太在意。
4.19 关注列表、粉丝列表
这两个功能差不多是一摸一样的
查询关注的实体:
关于一下几个位置的解释:
- 虽然set是没有顺序的,但是Redis里面内置 的有实现类,可以实现有序。
- 注意进行判断,在页面进行展示
- score.longValue() 为什么是这一个呢??
关于下面的解释:
这里进行的判定是为了避免有人随便乱写userId进行无用的查询,加个条件避免一下。
下面的这一部分我觉得可以写在service层中更加合适。
假如说没有登录,所有的用户对自己来说都是没有关注的状态,一定要将这个键值对补全了,不能没有这个键值对还进行访问。
查询粉丝:
和这个一毛一样的了,略
!!!!我还以为他会在这里首先进行一个判断。
4.23 优化登录模块
我们要使用Redis进行替代,因此这个并不推荐使用。
使用Redis缓存用户的数据这个功能是暂存,因为我们有数据库表,不需要存储很久。只是用来提高效率。
我们的做法,
优先从缓存中获取数值,如果可以获取就没问题。
如果不能获取就初始化缓存数据。
若数据库中的数据发生变更,我们可以更新缓存或者是删除缓存。我们一般是清除缓存数据。
在缓存中直接存储对象,它会序列化成为Json字符串。
我怎么觉得这个有安全问题,假如说,多个线程运行,缓存还没有来得及更改,但是实际上已经进行了更改。
但是目前看不出来性能的改变呢~~~
后来会讲的哦
最后: 若干个小问题
- 加入hash的value还是哈希怎么办。
- Redis本身就是一个hash吧。
- 现在我的电脑就是服务器,假如这台电脑关机了,那内存中的东西不就都消失了吗?
- 很困惑,哪些定义成异步刷新,为什么呢?假如把有些方法定义成不是异步的会怎样呢?
- 为空的数可以发送给页面吗,会发生什么情况。
- redis这么好为啥不都用Redis,压根就别用Mysql了。