欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

Redis6入门到精通

时间:2023-06-19
高性能,高可靠,高可扩展NoSQL数据库

前记

1、NoSQL数据库2、Redis采用单线程+多路IO复用技术3、Redis的"两大维度,三大主线" 一、安装配置Redis二、常用五大数据类型

Key1、字符串(String)-- ArrayList2、列表(List)-- quickList3、集合(Set)-- Hash4、哈希(Hash)5、有序集合(Zset) 三、Redis配置文件详解

1、### NETWORK 网络相关配置###2、### SECURITY 安全###3、### GENERAL 通用###4、### LIMITS 限制### 四、Redis的发布与订阅

1、什么是发布与订阅2、流程3、命令行实现 五、Redis新数据类型

1、Bitmaps2、HypeLogLog3、Geospatial 六、Jedis操作

1、测试连接及jedis方法调用2、模拟验证码发送 七、Redis6与SpringBoot整合八、事务_锁机制_秒杀

1、Redis事务定义2、Muti,Exec,discard3、事务的错误处理4、事务冲突的问题

1、悲观锁(效率低)2、乐观锁3、WATCH key [key]4、UNWATCH5、Redis事务三大特性 5、秒杀

1、核心代码演示2、秒杀并发模拟3、连接超时问题4、超卖问题5、库存遗留问题 九、持久化之RDB(Redis Database)默认开启

优点缺点1、是什么2、备份是如何执行的3、Fork4、配置文件(### SNAPSHOT###)5、rdb备份与恢复 十、持久化之AOF(Append only File) 默认不开启

优点缺点1、是什么2、AOF持久化流程3、开启AOF(若RDB同时开启,Redis听AOF的)4、AOF启动/修复/恢复5、AOF同步频率6、Rewrite压缩 十一、RDB和AOF到底如何选择十二、主从复制

1、简介2、演示(一主两从)3、常用三招

1、一主二仆2、薪火相传3、反客为主 4、复制原理5、哨兵模式(sentinel) 十三、集群


前记 1、NoSQL数据库

1、概述

2、NoSQL适用场景

3、NoSQL不适用场景


2、Redis采用单线程+多路IO复用技术

与Memcache的三点不同:支持多数据类型,支持持久化,单线程+多路IO复用

1、多路复用指使用一个线程来检查多个文件描述符(Socket)的就绪状态,
比如调用select和poll函数,传入多个文件描述符,如果有一个文件描述符就位,则返回,否则阻塞直到超时。
得到就绪状态后进行真正的操作可以在同一个线程里执行,也可以启用线程执行(比如使用线程池)、
就是说多路IO复用起到一个监视的效果,就绪后,Redis直接执行,不需要等待

2、串行 vs 采用多线程+锁(Memcached)vs 单线程+多路IO复用的比较

1、串行:阻塞IO,一件事一件事的做,在做当前事时,不能做其他事,有等待2、采用多线程+锁:非阻塞IO,一直重复做当前的事,没有等待3、单线程+多路IO复用:做某件事情需要一定的时间,可以监视这件事,我们可以做其他的事。多路IO复用有select,poll,epoll这些模式。select监测数量能力有限。poll监测数量没有限制,但是需要一个一个核查。配epoll监测数量没有限制,也不需要一个一个核查,直接看是否有一个正确的标识。



3、Redis的"两大维度,三大主线"

一、安装配置Redis

redis官网
1、下载最新版本tar.gz

2、安装C语言编译器gcc

yum install gcc查看gcc版本gcc --version

3、解压redis-tar.gz(解压到当前目录,本文的目录为/study,解压后为/study/redis-6.2.6)

tar -zxvf redis-6.2.6.tar.gz

4、编译为C文件(进入解压好的redis-6.2.6目录)

1、make安装bin启动器到/study/redis-6.2.6目录下2、make PREFIX=/study/redis-6.2.6 install

5、拷贝一份redis.conf到conf目录

cp /study/redis.6.2.6/redis.conf /study/redis.6.2.6/conf/redis.confvim /study/redis.6.2.6/conf/redis.conf开启后台运行daemonize no 改为 yes

6、以配置文件后台启动(进入/study/redis-6.2.6/bin目录),连接客户端

./redis-server ../conf/redis.conf ./redis-cli

7、关闭服务进程

客户端输入showdownps -ef|grep rediskill -9 pid



二、常用五大数据类型 Key

keys * 查看所有keyexists 判断key是否存在type 查看key是什么类型del 删除指定key数据unlink 根据value选择非阻塞删除,仅将key从keyspace元数据删除,真正的删除会在后续异步操作expire 10 设置10秒过期时间ttl 查看存活时间-1永不过期 -2已过期select ?切换数据库 默认0-15dbsize查看当前数据库key数量flushdb清空当前库flushall清空所有库


1、字符串(String)-- ArrayList

1、简介

简单动态字符串(Simple Dynamic String SDS)
类似ArrayList,采用预分配冗余空间的方式减少内存的频繁分配
二进制安全,最大存储512M

2、数据结构

3、命令

1、设值

set v设置单个键值mset v v设置多个键值setex

2、查询

get 查询单个键值mget 查询多个键值getrange 按下标查询键值strlen 获取值的长度

3、数字值操作(原子操作:得益于redis单线程,不会被其他线程打断的)

incr k储存的数字值增 1incrby k ?储存的数字值增 ?decr k 储存的数字值减 1decrby k ?储存的数字值减 ?


2、列表(List)-- quickList

1、简介

单键多值

2、数据结构:

3、命令

例:从左插入v1 v2 v3,实际从左到右为v3 v2 v1

1、插吐值

lpush/rpush k v1 v2 v3从左/右插入v1,v2,v3lpop/rpop k从左/右吐出一个值,吐完值键消失rpoplpush k1 k2从k1右边吐一个值插到k2左边

2、查询(并非吐值)

lrange k s e按照索引下标范围获得元素s start, e endlindex k i按照索引下标获得元素llen l获取列表长度

3、插值

linsert k before "v1" "new v1"在v1后面插入newv1

演示

4、特殊删除

lrem k 2 "v" 删除k左边的两个"v"

演示

5、替换

lset k i v将k下标为i的值换为v

演示

3、集合(Set)-- Hash

1、简介

自动排重

String类型的无序集合
底层是一个value为null的hash表,增删查复杂度都为O(1)
一个算法,随着数据的增加,执行时间的长短,如果是O(1),数据增加,查找数据的时间不变

2、数据结构

是dict字典,字典使用哈希表实现的
Java中的HashSet的内部实现使用的是HashMap,只不过所有的value都指向同一个对象。
Redis的set结构也一样,内部也使用Hash结构,所有的value指向同一个对象

3、命令

sadd k v1 v2 v3添加smembers k返回集合中所有元素srandmember k n随机从集合查询n个值sismember k v判断集合中是否有vscard k查询集合中元素个数srem k v1 v2删除集合中的某个元素spop k随机从集合k吐出某个值(吐出的值消失)smover k1 k2 v1把集合k1中的值v1移到k2sinter k1 k2返回两个集合的交集元素sunion k1 k2返回两个集合的并集元素sdiff k1 k2返回两个集合的差集元素(k1中的存在的,k2中不存在的)


4、哈希(Hash)

1、简介

Hash是一个String类型的field和value的映射表,类似于Map

2、数据结构

Hash类型对应数据结构为:ziplist(压缩列表),hashtable(哈希表),
当field-value长度较短且个数较少时,使用ziplist,否则使用hashtable

3、命令

hset k f v给k中的f赋值vhsetnx k f v给k中的f赋值v,仅当f不存在时例 hset user:1001 id 1设置user1001的id为1hmest k f1 v1 f2 v2 给k中的多个f赋值vhexist k f 查看k中是否存在fhkeys k查看k中的所有fieldhvals k查看k中的所有valuehget k f从k集合f查询vhincrby k f n为k中的f的v加上增量n

5、有序集合(Zset)

1、简介

2、数据结构

跳跃表实现过程

3、命令

zadd k s v s v将一个或多个member元素及其score值加入有序集k中zrange k s e 返回k中下标在s-e中的元素zrange k s e withscores 返回k中下标在s-e中的元素并带score(按评分从小到大)zrevrange k s e withscores 返回k中下标在s-e中的元素并带score(按评分从大到小)zrangebyscore k min max 返回评分在min max的元素(包含min,max)从小到大zrevrangebyscore k max min返回评分在max min的元素(包含min,max)从大到小zincrby k v为元素的scrore加上增量zrem k v删除k中指定元素zcount k min max统计个数,返回个数zrank k v返回v的排名,小的是第一名,排名从0开始



三、Redis配置文件详解 1、### NETWORK 网络相关配置###

1、bind

2、protected-mode

默认为yes,远程无法访问
修改为no,远程可以访问

3、Port

默认6379

4、tcp-backlog

5、timeout

2、### SECURITY 安全###

1.requirepass

修改配置文件中的 requirepass 参数,
把前面 # 注释去掉,后面 foobared 改成自己想用的密码,
重启redis即可。

进入客户端输入

auth ***连接

3、### GENERAL 通用###

1.daemonize

2.pidfile

3.loglevel

4.logfile

5、database 16

数据库设置默认16个 0-15

4、### LIMITS 限制###

1.maxclients

2.maxmemory

3.maxmemory-policy

4.maxmemory-samples



四、Redis的发布与订阅 1、什么是发布与订阅 2、流程 3、命令行实现

1.打开一个客户端订阅channel1

subscribe channel1

2.打开另一个客户端,给channe11发布消息hello

publish channel1 hello

3.打开第一个客户端收到hello



五、Redis新数据类型 1、Bitmaps

1.简介


2、命令

汇总

1、setbit 设置bitmaps中某个偏移量的值(0或1) *offset:偏移量从0开始设置成功返回02、getbit 获取bitmaps中某个偏移量的值3、bitcount [start end] 统计字符串从start字节到end字节比特值为1的数量4、bitop and(or/not/xor) [k1 k2...]获取多个k中的and(交集),or(并集),not(非),xor(异或) 的操作结果并将结果保存在destkey中返回值为and(or/not/xor)后的数量


1、设置bitmaps中某个偏移量的值

setbit 设置bitmaps中某个偏移量的值(0或1)*offset:偏移量从0开始设置成功返回0

实例


2、getbit

getbit 获取bitmaps中某个偏移量的值


3、bitcount(获取的数量是byte并非bit)

bitcount [start end] 统计字符串从start字节到end字节比特值为1的数量



4、bitop

bitop and(or/not/xor) [k1 k2...]获取多个k中的and(交集),or(并集),not(非),xor(异或)的操作结果并将结果保存在destkey中返回值为and(or/not/xor)后的数量

演示


Bitmaps与set的对比



2、HypeLogLog

1、简介

2、命令

1、pfadd

如果执行命令后HLL估计的近似基数发生变化,则返回1,否则返回0

pfadd 添加指定元素

2、pfcount

pfcount 计算HLL的近似基数,返回数量

3、pfmerge

pfmerge 将一个或多个HLL合并后的结果存在


3、Geospatial

1、简介

2、命令

1、geoadd

geoadd 添加地理位置(经度,纬度,名称)geoadd city 19.21 32.23 guangzhou

2、geopos

geopos 获取指定地区坐标值geopos city guangzhou

3、geodist

geodist [m|km|ft|mi]获取两个位置的直线距离 单位m默认值

4、georadius

georadius radius [m|km|ft|mi]以给定的经纬度为中心,找出某一半径radius内的元素



六、Jedis操作 1、测试连接及jedis方法调用

1、pom文件

redis.clients jedis 3.2.0

2、开放防火墙

systemctl status firewalld查看防火墙状态systemctl stop firewalld关闭防火墙

3、配置文件

1、bind127.0.0.1-》#bind127.0.0.1注释掉61行 2、protected-mode yes-》protected-mode no 关闭保护模式

4、重启redis

1、ps -ef|grep redis查看进程2、kill -9 pid杀掉进程

5、测试连接

public class JedisDemo01 { public static void main(String[] args) { Jedis jedis = new Jedis("192.168.88.129", 6379); String value = jedis.ping(); System.out.println(value); //输出PONG }}

6、测试String

public void demo1() { Jedis jedis = new Jedis("192.168.88.129", 6379); jedis.set("name", "jiali"); String name = jedis.get("name"); System.out.println(name); Set keys = jedis.keys("*"); for (String key : keys) { System.out.println("key:" + key); } }


2、模拟验证码发送


1、生成6位随机数

public static String getCode() { Random random = new Random(); String code = ""; for (int i = 0; i < 6; i++) { //取10之间的数字 int rand = random.nextInt(10); code += rand; } return code;}

2、每个手机每天只能发送三次,验证码放到redis中,设置过期时间

public static void sendCode(String phone) { Jedis jedis = new Jedis("192.168.88.129", 6379); jedis.auth("****"); //拼接key //手机发送次数key String countKey = phone + ":count"; //验证码key String codeKey = phone + ":code"; //每个手机每天只能发送三次 String count = jedis.get(countKey); if (count == null) { //没有发送次数,第一次发送 //设置发送次数是1 jedis.setex(countKey, 24 * 60 * 60, "1"); } else if (Integer.parseInt(count) <= 2) { //发送次数+1 jedis.incr(countKey); } else if (Integer.parseInt(count) > 2) { //发送三次,不能再发送 System.out.println("今天发送次数已经超过三次"); jedis.close(); //中断获取验证码后续操作 return; } //发送验证码放到redis String code = getCode(); jedis.setex(codeKey, 120, code); jedis.close();}

3、验证码校验

public static void verifyCode(String phone, String inputCode) { Jedis jedis = new Jedis("192.168.88.129", 6379); jedis.auth("****"); String codeKey = phone + ":code"; String redisCode = jedis.get(codeKey); if (redisCode.equals(inputCode)) { System.out.println("成功"); } else { System.out.println("失败"); }}

4、验证

1、sendCode("10086");2、进入redis-cli,查看keys *,查看验证码填入下面?3、verifyCode("10086","?");4、成功



七、Redis6与SpringBoot整合

1、pom

org.springframework.boot spring-boot-starter-data-redis org.apache.commons commons-pool2

2、配置文件

spring: redis: host: 192.168.88.129 port: 6379 password: **** database: 0 #连接超时时间 timeout: 1800000 lettuce: pool: #最大连接数 max-active: 20 #最大阻塞等待时间(负数表示没限制) max-wait: -1 #最大最小空间连接 max-idle: 5 min-idle: 0

3、RedisConfig

package com.laptoy.redis.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;import org.springframework.cache.CacheManager;import org.springframework.cache.annotation.CachingConfigurerSupport;import org.springframework.cache.annotation.EnableCaching;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.cache.RedisCacheConfiguration;import org.springframework.data.redis.cache.RedisCacheManager;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.RedisSerializationContext;import org.springframework.data.redis.serializer.RedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer;import java.time.Duration;@EnableCaching@Configurationpublic class RedisConfig extends CachingConfigurerSupport { @Bean public RedisTemplate redisTemplate(RedisConnectionFactory factory) { RedisTemplate template = new RedisTemplate<>(); RedisSerializer redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常 om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); template.setConnectionFactory(factory); //key序列化 template.setKeySerializer(redisSerializer); //value序列化 template.setValueSerializer(jackson2JsonRedisSerializer); //value hashmap序列化 template.setHashKeySerializer(jackson2JsonRedisSerializer); return template; } @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { RedisSerializer redisSerializer = new StringRedisSerializer(); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); //解决查询缓存转换异常的问题 ObjectMapper om = new ObjectMapper(); // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常 om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); //配置序列化(解决乱码问题),过期时间600秒 RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofSeconds(600)) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)) .serializevaluesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)) .disableCachingNullValues(); RedisCacheManager cacheManager = RedisCacheManager.builder(factory) .cacheDefaults(config) .build(); return cacheManager; }}

4、测试Controller

@RestControllerpublic class RedisTestController { @Autowired RedisTemplate redisTemplate; @GetMapping("/test") public String redisTest() { redisTemplate.opsForValue().set("name", "jiali"); String name = (String) redisTemplate.opsForValue().get("name"); return name; }}



八、事务_锁机制_秒杀
1、Redis事务定义 2、Muti,Exec,discard 3、事务的错误处理

1、组队中某个命令出现报告错误,执行时整个的所有队列都会被回滚

2、执行阶段某个命令报错,则只有报错的不会执行,其他正常执行


4、事务冲突的问题

例子:同一个账户有10000块,三个人登录同一个账户同一时刻购买东西

1、悲观锁(效率低)


2、乐观锁



3、WATCH key [key]


客户端1

客户端2

4、UNWATCH

被watch的客户端的key成功执行事务后,自动取消watch状态

5、Redis事务三大特性 5、秒杀 1、核心代码演示

1.客户端添加秒杀商品 iphone 10件

set sk:iphone:kc 10

2.获取随机用户id

public static String getUid() { Random random = new Random(); String uid = ""; int rand = random.nextInt(20); uid += rand; return uid;}

3.秒杀过程

public static void doSecKill(String uid, String pid) { if (uid == null || pid == null) { System.out.println("用户名或商品名不能为空"); } Jedis jedis = new Jedis("192.168.88.129", 6379); jedis.auth("****"); //1、库存key String kcKey = "sk:" + pid + ":kc"; //2、用户key String userKey = "sk:" + pid + ":user"; //3、判断秒杀是否开始 String kc = jedis.get(kcKey); if (kc == null) { System.out.println("秒杀未开始"); jedis.close(); //中止 return; } //4、判断用户是否重复秒杀 if (jedis.sismember(userKey, uid)) { System.out.println("您已经秒杀成功,无法重复参与"); jedis.close(); //中止 return; } //5、判断库存数量 if (Integer.parseInt(kc) <= 0) { System.out.println("秒杀已结束"); jedis.close(); //中止 return; } //6、秒杀过程 //6.1、库存-1 jedis.decr(kcKey); //6.2、把秒杀用户添加到清单里 jedis.sadd(userKey, uid); System.out.println("秒杀成功"); jedis.close();}

4.测试

public static void main(String[] args) { for (int i = 0; i <20 ; i++) { doSecKill(getUid(), "iphone"); }}


2、秒杀并发模拟

自行模拟tomcat测试,此处省略

1.使用工具ab模拟测试
centos6默认安装,centos7需要手动安装

2.安装ab

yum install httpd-tools

3.命令

ab --helpab http://....-n 请求数量-c 请求并发量-p post请求时提交参数-T 指定参数类型post/put


3、连接超时问题

1.使用数据库连接池解决–单例模式懒加载,双重校验锁

import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;import redis.clients.jedis.JedisPoolConfig;public class JedisPoolUtil{ private static volatile JedisPool jedisPool = null; private JedisPoolUtil() { } public static JedisPool getJedisPoolInstance() { if (null == jedisPool) { synchronized (JedisPoolUtil.class) { if (null == jedisPool) { JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxTotal(200); poolConfig.setMaxIdle(32); poolConfig.setMaxWaitMillis(100 * 1000); //超时是否等待 poolConfig.setBlockWhenExhausted(true); //测试连接状态 ping pong poolConfig.setTestOnBorrow(true); jedisPool = new JedisPool(poolConfig, "192.168.88.129", 6379, 60000, "****"); } } } return jedisPool; } public static void release(JedisPool jedisPool, Jedis jedis) { if (null != jedis) { jedisPool.returnResource(jedis); } }}

2.测试连接

JedisPool jedisPoolInstance = JedisPoolUtil.getJedisPoolInstance();Jedis jedis = jedisPoolInstance.getResource();

4、超卖问题

1.乐观锁解决

代码演示
1.注释秒杀过程

//6、秒杀过程//6.1、库存-1//jedis.decr(kcKey);//6.2、把秒杀用户添加到清单里//jedis.sadd(userKey, uid);

2.加了乐观锁

jedis.watch(kcKey);Transaction multi = jedis.multi();multi.decr(kcKey);multi.sadd(userKey, uid);List result = multi.exec();if (result == null || result.size() == 0) { System.out.println("秒杀失败了,请重试"); jedis.close(); return;}


5、库存遗留问题

1.Lua脚本

测试代码

import java.io.IOException;import java.util.HashSet;import java.util.List;import java.util.Set;import org.apache.commons.pool2.impl.GenericObjectPoolConfig;import org.slf4j.LoggerFactory;import ch.qos.logback.core.joran.conditional.ElseAction;import redis.clients.jedis.HostAndPort;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisCluster;import redis.clients.jedis.JedisPool;import redis.clients.jedis.JedisPoolConfig;import redis.clients.jedis.ShardedJedisPool;import redis.clients.jedis.Transaction;public class SecKill_redisByscript {private static final org.slf4j.Logger logger =LoggerFactory.getLogger(SecKill_redisByscript.class) ;public static void main(String[] args) {JedisPool jedispool = JedisPoolUtil.getJedisPoolInstance(); Jedis jedis=jedispool.getResource();System.out.println(jedis.ping());Set set=new HashSet();//doSecKill("201","sk:0101");}static String secKillscript ="local userid=KEYS[1];rn" + "local prodid=KEYS[2];rn" + "local qtkey='sk:'..prodid..":qt";rn" + "local usersKey='sk:'..prodid..":usr";rn" + "local userExists=redis.call("sismember",usersKey,userid);rn" + "if tonumber(userExists)==1 then rn" + " return 2;rn" + "endrn" + "local num= redis.call("get" ,qtkey);rn" + "if tonumber(num)<=0 then rn" + " return 0;rn" + "else rn" + " redis.call("decr",qtkey);rn" + " redis.call("sadd",usersKey,userid);rn" + "endrn" + "return 1" ; static String secKillscript2 = "local userExists=redis.call("sismember","{sk}:0101:usr",userid);rn" +" return 1";public static boolean doSecKill(String uid,String prodid) throws IOException {JedisPool jedispool = JedisPoolUtil.getJedisPoolInstance();Jedis jedis=jedispool.getResource(); //String sha1= .secKillscript;String sha1= jedis.scriptLoad(secKillscript);Object result= jedis.evalsha(sha1, 2, uid,prodid); String reString=String.valueOf(result);if ("0".equals( reString ) ) {System.err.println("已抢空!!");}else if("1".equals( reString ) ) {System.out.println("抢购成功!!!!");}else if("2".equals( reString ) ) {System.err.println("该用户已抢过!!");}else{System.err.println("抢购异常!!");}jedis.close();return true;}}



九、持久化之RDB(Redis Database)默认开启 优点

(1)节省磁盘空间(2)恢复速度快 缺点

(1) Fork的时候,内存的数据被克隆了一份,大致2倍的膨胀率需要考虑(2)虽然fork时使用了写时拷贝技术,但是如果数据庞大比较消耗性能(3)在备份周期一定间隔时间做一次备份,但是如果Redis意外down掉的话,就会丢失最后一次修改 1、是什么

在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照
Redis将内存存储和持久化存储相结合,即可提供数据访问的高效性,又可保证数据存储的安全性。

2、备份是如何执行的

当满足条件时,redis需要执行RDB的时候服务器会执行以下操作:

1.redis调用系统的fork()函数创建一个子进程2.子进程将数据集写入一个临时的RDB文件3.当子进程完成对临时的RDB文件的写入时,redis用新的RDB文件来替换原来旧的RDB文件,并将旧的RDB文件删除

redis在进行快照的过程中不会对RDB文件进行修改,只有快照结束后才会将旧快照替换成新快照,也就是说任何时候RDB都是完整的

3、Fork 4、配置文件(### SNAPSHOT###)

1.Save
1、默认1分钟内改了1万次,或5分钟内改了100次,或15分钟改了1次执行
2、如何禁用
不设置save指令,或者给save传入空字符串
3、动态禁止

redis-cli config set save ""

2.Save VS bgSave
1、save:只管保存,其他不管,全部阻塞。手动保存,不建议
2、bgsave:Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。
   可以通过lastsave命令获取最后一次成功执行快照的时间

3.stop-writes-on-bgsave-error 停止写入
当Redis无法写入磁盘的话,直接关掉Redis的写操作。推荐开启
4.rdbcompression 压缩文件
对于存储到磁盘中的快照,可以设置是否进行压缩存储,redis会采用LZF算法进行压缩。推荐开启
缺点:消耗CPU

5.rdbchecksun 检查完整性
存储快照后,redis可以使用CRC64算法进行数据校验。推荐开启
缺点:消耗CPU

5、rdb备份与恢复

config get dir查看文件目录(xxx.rdb文件放到该目录自动进行恢复)



十、持久化之AOF(Append only File) 默认不开启 优点

1、备份机制更稳健,丢失数据概率较低2、可读的日志文件,通过操作AOF文件,可以处理误操作3、AOF以appen-only(追加)的模式写入,所以没有任何磁盘寻址的开销,写入性能非常高。 缺点

1、比RDB占用更多磁盘空间2、恢复备份速度慢,不适合做冷备3、每次读写都同步,有一定的性能压力4、存在个别bug,造成恢复不能
bin目录输入 redis-check-aof --fix xxx.aof可以修复一些操作 1、是什么

1、以日志的形式来记录每个写操作2、只许追加文件但不能改写文件3、Redis启动之初会重新构建数据 2、AOF持久化流程

1、客户端的请求命令会被append追加到AOF缓存区中2、AOF缓存区根据AOF持久化策略[always,everysec,no]将操作sync同步到AOF文件3、AOF文件超过重写策略或手动重写时,会对AOF文件进行rewrite重写,压缩AOF文件容量4、Redis服务重启时,重写load加载AOF文件的写操作达到数据恢复的目的 3、开启AOF(若RDB同时开启,Redis听AOF的)

appendonly yes开启AOFappendfilename "xxx.aof"自定义文件名称

4、AOF启动/修复/恢复

1、恢复

config get dir查看文件目录(xxx.aof文件放到该目录自动进行恢复)

2、异常修复(bin目录)

redis-check-aof --fix xxx.aof继续输入y

5、AOF同步频率

appendfsync always始终同步。性能较差但完整性好appendfsync everysec每秒同步。如果宕机,本秒的数据可能丢失appendfsync no不主动同步,把同步时机交给操作系统

6、Rewrite压缩

set k1 v1 + set k2 v2 压缩成 set k1 v1 k2 v2

1、auto-aof-rewrite-percentage:设置重写的基准值,文件达到100%开始重写2、auto-aof-rewrite-min-size:设置重写的基准值,最小文件64M,达到这个值开始重写

例如:
文件达到70MB开始重写,重写为50MB,下次当100MB开始重写
系统载入时或者上次重写完毕时,Redis会记录此时AOF大小,设为base_size
如果Redis的下一次AOF大小>=base_size+base_size*100%且当前大小大于64MB时开始重写



十一、RDB和AOF到底如何选择

(1)不要仅仅使用RDB这样会丢失很多数据。(2)也不要仅仅使用AOF,因为这一会有两个问题,第一通过AOF做冷备没有RDB做冷备恢复的速度快;第二RDB每次简单粗暴生成数据快照,更加健壮。(3)综合AOF和RDB两种持久化方式,用AOF来保证数据不丢失,作为恢复数据的第一选择;用RDB来做不同程度的冷备,在AOF文件都丢失或损坏不可用的时候,可以使用RDB进行快速的数据恢复。



十二、主从复制 1、简介

读写分离–主机写 从机读容灾快速恢复主机更新后根据配置和策略,自动同步到从机 2、演示(一主两从)

1.创建msconf文件夹存放主从配置文件

2.复制一份redis.conf到msconf

开启守护进程 daemonize yes关闭AOF持久化 appendonly no

3.配置三个配置文件

include /pidfile /portdbfilename

4.开启服务

5.查看服务器状态

info replication

6、配置从机

slaveof 127.0.0.1 port

3、常用三招

1、从服务器如果停止了,重启变为master,需要重新执行该命令变为slave2、主服务器如果停止了,重启还是连接着两台从服务器(你大哥还是你大哥) 1、一主二仆

一台Master多台Slave

2、薪火相传

Master的slave可以被另一台服务器slaveof

3、反客为主

Master挂掉后其中一台slave执行
slaveof no one
成为新的Master

4、复制原理

1、slave启动成功连接到master后会发送一个sync同步命令2、当master接到slave发送过来的同步消息,首先把master数据进行持久化成rdb文件,把rdb文件发送到slave,slave拿到rdb文件进行读取3、每次主服务器进行写操作后,和从服务器进行数据同步

1、全量复制:slave接收到数据库文件数据后,将其存盘并加载到内存中
2、增量复制:master继续将新的所有收集到的修改命令依次传给slave
3、但只要时重新连接master,一次完成同步(全量复制)将被自动执行

5、哨兵模式(sentinel)

反客为主的自动版,Master故障自动从Slave选出新的Master

1.新建sentinel.conf文件到/study/redis-6.2.6/msconf/
mymaster为监控对象起的服务器名称 ,1为至少有多少个哨兵同意迁移的数量

sentinel monitor mymaster 127.0.0.1 6379 1

2.启动哨兵

./redis-sentinel /study/redis-6.2.6/msconf/sentinel.conf


3.身份切换
当Master宕机,重新选举一个Slave成为新的Master,旧的Master重启后也成为Slave

4.选举优先级 redis.conf

replica-priority 100 值越小优先级越高

1、选择优先级靠前的2、选择偏移量最大的(获得原主机数据最全的)3、选择runid最小的(每个redis实例启动后随机生成40为runid)

5.复制延迟
由于所有写操作都在Master执行,然后同步更新到Slave,所以从Master同步到Slave机器有一点的延迟,当系统很繁忙的时候,延迟问题更严重,Slave机器的增加也会使这个问题更严重



十三、集群

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。