1. redis基础
2.linux下启动redis
3.Redis的数据类型
4.常用命令
5.通用命令
6.使用jedis操作redis
7.SpringData操作mysql数据库
8.Redis持久化
9.主从复制
10.哨兵模式–主节点发生问题,子节点变为主节点
11.redis海量数据,海量写 ----- 分片集群
12.多级缓存
13.Lua语法
14.Redis预热
15.缓存同步
Redis 是基于内存的key-value结构数据库
1.基于内存存储没读写性能高
2.存储热点数据(热点商品、新闻)
3.应用广泛
Nosql,数据与数据之间没有任何关系,非关系型数据库
缓存、消息队列
安装: make可用make MALLOC=libc替换使用
当前目录下:./redis-server 启动redis
cd /usr/local/redis-4.0.0/src 找到src目录
./redis-cli 启动程序
修改redis的配置文件
vim redis.conf 修改daemonize yes
src/redis-server ./redis.conf
可以让redis砸在后台运行
修改 redis.conf的密码 requirepassword
重新启动该文件
ps -ef | grep redis 查看进程
kill -9 23789 杀掉该进程
src/redis-server ./redis.conf 重新启动该配置文件
src/redis-cli -h localhost -p 6379 启动redis
auto 输入密码
exit 退出
redis.conf # 掉

ps -ef | grep redis 查询redis的端口号
kill -9 70771 杀掉端口号
src/redis-server ./redis.conf 重新启动
firewall-cmd --reload 关闭防火墙
firewall-cmd --add-port=6379/tcp 开放端口
windows就可以通过
.\redis-cli.exe -h ip -p 端口 -a 密码
key为string,
value为:
字符串常用命令
hash操作命令
HSET key1 key2 value 将哈希表key1字段 key2 和value设置为值
HGET key1 key2 根据哈希表key1获取key2 的value
HDEL key value1,value2 删除哈希表key1的 key2的指定字段
HKEYS key1 获取哈希表key1的所有的字段
HVALS key1 获取哈希表key1的所有字段的值
hgetall key1 获取哈希表key1的所有字段和值
列表 每一个列表都是字符串类型的
set集合 唯一 无序的集合
sorted set 有序集合
有序集合是string类型的集合,不允许重复数据,每一个元素都会关联一个double类型的分数,redis通过分数进行集合中从大到小的排序,有序集合的成员是唯一的,分数可以重复.
@SpringBootTest
class DemoApplicationTests {
/**
*
* redis.clients
* jedis
* 2.8.0
*
*/
@Test
void contextLoads() {
//1.获取连接
Jedis jedis = new Jedis("localhost",6379); //本地
//2.执行具体的操作
jedis.set("name","xiaowang"); //新增
//3.关闭连接
jedis.close();
}
@Test
void TestJedis(){
Jedis jedis = new Jedis("localhost",6379); //本地
String s = jedis.get("name"); //查询
System.out.println(s);
}
@Test
void Del(){
Jedis jedis = new Jedis("localhost",6379); //本地
Long name = jedis.del("name"); //删除
System.out.println(name);
}
@Test
void Hash(){
Jedis jedis = new Jedis("localhost",6379); //本地
// Long hset = jedis.hset("1001", "name", "xiaowang");
String hget = jedis.hget("1001", "name");
System.out.println(hget);
// System.out.println(lrange);
}
}
依赖
org.springframework.boot
spring-boot-starter-data-redis
String类型的操作
@Autowired
private RedisTemplate redisTemplate;
/**
* 操作string的数据
*/
@Test
public void Test01(){
// 获取String对象
ValueOperations valueOperations = redisTemplate.opsForValue();
valueOperations.set("name1","xiaoye");
String name = (String)valueOperations.get("name1");
// 设置十秒钟的过期时间
redisTemplate.opsForValue().set("age","10",111l, TimeUnit.SECONDS);
// 不存在时,设置key
Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("name2", "xiaowang");
System.out.println(aBoolean);
}
Hash的操作
/**
* 操作Hash类型的数据
*/
@Test
public void Hash(){
HashOperations hashOperations = redisTemplate.opsForHash();
//存值
hashOperations.put("01","11","xiaowang");
hashOperations.put("01","12","xiaoye");
//取值
String o =(String) hashOperations.get("01", "11"); //获取key为01的11的值
String o1 =(String) hashOperations.get("01", "12");
System.out.println(o);
System.out.println(o1);
//获取Hash结果中所有的字段
Set keys = hashOperations.keys("01");
for (Object j : keys){
System.out.println(j);
}
//获取Hash结构中所有的值
List values = hashOperations.values("01");
for (Object j : values){
System.out.println(j);
}
}
List的操作
/**
* 操作list的数据
*/
@Test
public void List(){
ListOperations listOperations = redisTemplate.opsForList();
// 存入list单个数据
listOperations.leftPush("1","a");
//存入list多个数据
listOperations.leftPushAll("1","b","c","d");
//查询所有元素
List<String> range = listOperations.range("1", 0, -1);
for (String s :range){
System.out.println(s);
}
//获取集合的长度
Long size = listOperations.size("1");
int i = size.intValue();
for (int i1 = 0; i1 < i; i1++) {
//移除集合最后一个元素
String o =(String) listOperations.rightPop("1");
System.out.println("删除当前元素"+o+"执行"+i1+"次");
}
}
set的操作方法
/**
* Set 类型的操作
*/
@Test
public void Set(){
SetOperations setOperations = redisTemplate.opsForSet();
//Set存值
setOperations.add("123","123","456");
// 删除
setOperations.remove("123","123");
//Set取值
Set<String> members = setOperations.members("123");
for (String c : members){
System.out.println("Set的值为:"+c);
}
}
zset的操作方法
/**
* sorted set 有序集合,不能重复
*/
@Test
public void sortedSet(){
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
//存值
zSetOperations.add("zset","a",1);
zSetOperations.add("zset","b",2);
zSetOperations.add("zset","c",1.5);
//取值
Set<String> zset = zSetOperations.range("zset", 0, -1);
for (String s : zset){
System.out.println("第一组"+s);
}
//修改分数
zSetOperations.incrementScore("zset","a",10);
Set<String> zset1 = zSetOperations.range("zset", 0, -1);
for (String s : zset1){
System.out.println("第二组"+s);
}
//删除分数
zSetOperations.remove("zset","a","b");
}
通用操作
/**
* 通用操作
*/
@Test
public void tets(){
// 获取redis中所有的key
Set<String> keys = redisTemplate.keys("*");
for (String s : keys){
System.out.println("获取所有的key"+s);
}
//判断某个key是否存在
Boolean zset = redisTemplate.hasKey("zset");
System.out.println("当前key是否存在"+zset);
//删除指定的key
Boolean zset1 = redisTemplate.delete("zset");
System.out.println("当前是否删除"+zset1);
// 获取指定key对应的value的数据类型
DataType type = redisTemplate.type("123");
String name = type.name();
System.out.println("获取指定的key"+name);
}

原理:






同步原理

全量同步原理(主节点判断replid是否一致,id不一致为第一次,从节点拉取主节点版本信息,主节点执行bgsave,生成RDB文件,发送给从节点,从节点删除本地文件,加载文件,如果当前发生了数据操作,主节点添加repl_baklog,并将log中的命令发生给从节点,从节点接收命令,执行命令,这样完成与主节点的同步)

增量同步(主节点判断replid是否一致,id一致为不是第一次,从节点从主节点repl_baklog文件中同步尚未同步的数据)


****当主节点发送异常时,推选其他从节点为主节点,将异常主节点修改为从节点 ****




计算当前操作的哈希值,分配到不同的redis进行存储

**主节点出现问题后,主节点拒绝所有数据访问,主节点向从节点发送offset数据,判断从节点数据是否同步,同步的话进行数据迁移,子节点标注自己为主节点,向其他从节点广播自己的主节点,收到广播后,处理用户的请求,宕机的主节点恢复后,变为从节点 **

redis和本地缓存搭配使用

jvm缓存查询

设置jvm缓存

public class CaffeineTest {
/*
基本用法测试
*/
@Test
void testBasicOps() {
// 创建缓存对象
Cache<String, String> cache = Caffeine.newBuilder().build();
// 存数据
cache.put("gf", "迪丽热巴");
// 取数据,不存在则返回null
String gf = cache.getIfPresent("gf");
System.out.println("gf = " + gf);
// 取数据,不存在则去数据库查询
// 先查询key为"defaultGF"的数据,如果不存在,则查询数据库的数据,也就是key方法体的数据
String defaultGF = cache.get("defaultGF", key -> {
// 这里可以去数据库根据 key查询value
return "柳岩";
});
System.out.println("defaultGF = " + defaultGF);
}
/*
基于大小设置驱逐策略:
*/
@Test
void testEvictByNum() throws InterruptedException {
// 创建缓存对象
Cache<String, String> cache = Caffeine.newBuilder()
// 设置缓存大小上限为 1
.maximumSize(1)
.build();
// 存数据
cache.put("gf1", "柳岩");
cache.put("gf2", "范冰冰");
cache.put("gf3", "迪丽热巴");
// 延迟10ms,给清理线程一点时间
Thread.sleep(10L);
// 获取数据
System.out.println("gf1: " + cache.getIfPresent("gf1"));
System.out.println("gf2: " + cache.getIfPresent("gf2"));
System.out.println("gf3: " + cache.getIfPresent("gf3"));
}
/*
基于时间设置驱逐策略:
*/
@Test
void testEvictByTime() throws InterruptedException {
// 创建缓存对象
Cache<String, String> cache = Caffeine.newBuilder()
.expireAfterWrite(Duration.ofSeconds(1)) // 设置缓存有效期为 10 秒
.build();
// 存数据
cache.put("gf", "柳岩");
// 获取数据
System.out.println("gf: " + cache.getIfPresent("gf"));
// 休眠一会儿
Thread.sleep(1200L);
System.out.println("gf: " + cache.getIfPresent("gf"));
}
}







mysql在进行增删改时,会将日志记录在binary log 目录中 ,slave会开启线程读取文件,放入relay log中,再开启线程去读log中操作,canal伪装成一个slave节点,完成相应的操作
加入jar包

配置监听器,监听sql操作


