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 基础
Redis 是基于内存的key-value结构数据库
1.基于内存存储没读写性能高
2.存储热点数据(热点商品、新闻)
3.应用广泛
Nosql,数据与数据之间没有任何关系,非关系型数据库
缓存、消息队列
linux下启动redis
安装: 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为:
- String 字符串类型
- hash 哈希 适合存储对象
- list 列表,没有重复元素
- set 集合,没有重复元素,相同的元素会被覆盖掉
- sorted set 有序集合,没有重复元素,相同的元素会被覆盖掉
常用命令
字符串常用命令
- set key value 设置指定的key
- get key 获取指定的key
- setex key 时间 value 设置指定的key的值,中间设置过期时间
- setnx key value 只要key不存在,设置
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的所有字段和值
列表 每一个列表都是字符串类型的
- LPUSH key value 插入到头部 先插入的数据在尾部
- LRANGE key 范围(x 空格 x) 获取元素 ,获取的数据是后插入的数据
- rpop key 移除并获取最后一个元素 移除最早插入的数据
- llen key 获取元素长度
- brpop key timeout 移除并获取最后一个元素,如果当前没有删除的元素,则等待设置的时间
set集合 唯一 无序的集合
- SADD KEY 元素1 元素2 ->添加元素
- SMEMBERS key ->返回集合中的所有成员
- SCARD key ->获取所有成员的个数
- SINTER KEY KEY2 ->返回所有集合的交集(两个集合相同的)
- SUNION KEY1 KEY2 ->返回所有集合的并集(两个集合相加,相同的排除)
- SDIFF KEY1 KEY2 ->返回所有指定集合的差集 (第一个减去第二个集合剩余的数据)
- SREM key name1 name2 ->移除集合一个或多个成员
sorted set 有序集合
有序集合是string类型的集合,不允许重复数据,每一个元素都会关联一个double类型的分数,redis通过分数进行集合中从大到小的排序,有序集合的成员是唯一的,分数可以重复.
- zadd key 值 元素 值 元素 新增sorted set集合
- zrange key 值 值 从小到大查询两个数字之间的元素 withscores(显示值元素)
- zincrby key 值 元素 增加分数
- zrem key 移除元素
通用命令<div= ‘5’ />
- keys * 查询有多少key
- exists key 查看key是否存在
- type key 返回key所存储的类型
- ttl key 返回给定的key 的剩余生存时间
- DEL key 删除指定的key
- flushall 清除所有缓存
java中操作redis->jedis
@SpringBootTest
class DemoApplicationTests {
/**
* <dependency>
* <groupId>redis.clients</groupId>
* <artifactId>jedis</artifactId>
* <version>2.8.0</version>
* </dependency>
*/
@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);
}
}
使用springdata操作redis
<dependency> 依赖
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
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);
}
主从复制 持久化
RDB持久化
- RDB方案在redis内部开启了,每次服务器关闭时,执行一次Save,完成一次RDB操作
- 可用设置RDB的设置,如多少秒执行一次
- save主进程(主进程执行,其他操作不能执行) bgsave 子进程
原理:
AOF持久化
- 在conf文件设置
AOF执行的每一次操作,经过设定的同步秒数(默认为1),写在定义的文件中,如果服务器突然关闭,读取这个文件即可恢复数据。
- 压缩文件–触发重写
RDP与AOF的不同
主从复制
- 将B设置为A的子节点
-
同步原理
-
全量同步原理(主节点判断replid是否一致,id不一致为第一次,从节点拉取主节点版本信息,主节点执行bgsave,生成RDB文件,发送给从节点,从节点删除本地文件,加载文件,如果当前发生了数据操作,主节点添加repl_baklog,并将log中的命令发生给从节点,从节点接收命令,执行命令,这样完成与主节点的同步)
-
增量同步(主节点判断replid是否一致,id一致为不是第一次,从节点从主节点repl_baklog文件中同步尚未同步的数据)
- 区别
哨兵管理
****当主节点发送异常时,推选其他从节点为主节点,将异常主节点修改为从节点 ****
redisTemplate使用哨兵模式
配置集群的读写分离
分片集群
计算当前操作的哈希值,分配到不同的redis进行存储
故障转移
**主节点出现问题后,主节点拒绝所有数据访问,主节点向从节点发送offset数据,判断从节点数据是否同步,同步的话进行数据迁移,子节点标注自己为主节点,向其他从节点广播自己的主节点,收到广播后,处理用户的请求,宕机的主节点恢复后,变为从节点 **
多级缓存
JVM的进程缓存
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"));
}
}
LUA
Redis预热功能
缓存同步 Canal
-
mysql在进行增删改时,会将日志记录在binary log 目录中 ,slave会开启线程读取文件,放入relay log中,再开启线程去读log中操作,canal伪装成一个slave节点,完成相应的操作
-
加入jar包
-
配置监听器,监听sql操作
- 标记表中的字段