**初识Redis**
一. 为什么在多线程并发情况下,以Redis实现的“自增ID工具”能保证ID按顺序自增长且不重复:
此处的自增ID工具用的是redis的增加score方法 , 每调用一次 , redis的key ‘id’ 就自增1 , 返回值为增加后的数值 , 故获取id的动作不会有重复值.
/**
* “自增ID工具”
* @description:
* @author: Jeff
* @date: 2020年9月21日
* @return
*/
public Long getId(){
return redisTemplate.opsForValue().increment("id", 1);
}
二 . 描述Redis之List类型分页实现过程,企业里存在类似的场景。
从redis中rang数据时 , 用的是按索引rang , 页面请求的页码和pageSize传到后台 , 调用redis的rang方法 ,
int startIndex = (pageNum-1)pageSize;作为起始索引 ,
int endIndex = pageNumpageSize;作为截至索引 , 就能获取到指定索引区间的数据返回页面 .
package com.chencan.redis.controller;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.chencan.redis.domain.ScoreType;
import com.chencan.redis.domain.Student;
@Controller
public class StudentController {
@Resource
private RedisTemplate redisTemplate;
/**
* 6.页面数据展示:(25分)
(1)按原型图效果展示数据。(5分)
(2)正确显示“课程数”,课程数是学生除了成绩为“-”外课程的数量。(4分)
(3)正确显示“不及格数”,不及格数是除了成绩为“-”外,低于60分的课程数量。(5分)
(4)正确显示“平均成绩”,平均成绩是学生除了成绩为“-”外课程成绩的平均数。(5分)
(5)正确分页,每页展示10条。提示:必须在Redis中分好页,不得全部取出通过Java在虚拟机内存中分页。(6分)
* @description:
* @author: Jeff
* @date: 2020年9月21日
* @param pageNum
* @param pageSize
* @param model
* @return
*/
@RequestMapping("list")
public String list(@RequestParam(defaultValue="1")Integer pageNum,@RequestParam(defaultValue="9")Integer pageSize,Model model){
ListOperations<String, Student> opsForList = redisTemplate.opsForList();
int startIndex = (pageNum-1)*pageSize;
int endIndex = pageNum*pageSize;
List<Student> list = opsForList.range("studentList", startIndex, endIndex);
for (Student student : list) {
Float chinese = student.getChinese();
Float english = student.getEnglish();
Float maths = student.getMaths();
Float c = student.getC();
Float css = student.getCss();
Float cf = student.getCf();
Float ds = student.getDs();
Float dsi = student.getDsi();
ScoreType os= student.getOs();
Float network = student.getNetwork();
int classCount=0;
//String osname=os.getDiplayName();
int fcount=0;
int count =0;
//System.out.println(osname);
if(chinese==null){
}else{
classCount++;
count+=chinese;
if(chinese<60){
fcount++;
}
}
if(english==null){
}else{
classCount++;
count+=english;
if(english<60){
fcount++;
}
}
//数学
if(maths==null){
}else{
classCount++;
count+=maths;
if(maths<60){
fcount++;
}
}
if(c==null){
}else{
classCount++;
count+=c;
if(c<60){
fcount++;
}
}
if(css==null){
}else{
classCount++;
count+=css;
if(css<60){
fcount++;
}
}
if(cf==null){
}else{
classCount++;
count+=cf;
if(cf<60){
fcount++;
}
}
if(ds==null){
}else{
classCount++;
count+=ds;
if(ds<60){
fcount++;
}
}
if(dsi==null){
}else{
classCount++;
count+=dsi;
if(dsi<60){
fcount++;
}
}
if(network==null){
}else{
classCount++;
count+=network;
if(network<60){
fcount++;
}
}
student.setAvg(count/classCount);
student.setClassCount(classCount);
student.setFcount(fcount);
}
model.addAttribute("list", list);
model.addAttribute("pageNum", pageNum);
model.addAttribute("total", opsForList.size("studentList")/pageSize);
return "list";
}
/**
* 7.测试持久化机制:(10分)
(1)保持Web项目不停止运行的情况下,通过Redis客户端命令关闭Redis服务端。(3分)
(2)重新启动Redis服务端。(2分)
(3)刷新或继续访问页面,数据继续显示。数据丢失则全扣此大项13分。(5分)
*/
}
三 . Redis的持久化机制。
持久化流程
(1)客户端向服务端发送写操作(数据在客户端的内存中)。
(2)数据库服务端接收到写请求的数据(数据在服务端的内存中)。
(3)服务端调用write这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中)。
(4)操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中)。
(5)磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上)。
实际使用中 , 这个数据存储过程会发生主要两种故障 ,
即时保存了数据 , 保存的数据也可能已经损坏:
1)Redis数据库发生故障,
2)操作系统发生故障,
Redis如何保证上面5步保存动作 : 它提供了两种机制
RDB和AOF
1 . RDB机制
RDB其实就是把数据以快照的形式保存在磁盘上。什么是快照呢,你可以理解成把当前时刻的数据拍成一张照片保存下来。
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。也是默认的持久化方式,这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。
2 . AOF机制
全量备份总是耗时的,有时候我们提供一种更加高效的方式AOF,工作机制很简单,redis会将每一个收到的写命令都通过write函数追加到文件中。通俗的理解就是日志记录。
每当有一个写命令过来时,就直接保存在我们的AOF文件中。