redis 应该知道的一些东西

1、redis简介

redis官方中文网站:http://www.redis.cn

官方介绍如下:
Redis是一个开源的(BSD)许可的,内存中的数据结构存储系统,它可以用作数据库、缓存、消息中间件。
Redis支持如字符串(strings)、散列(hashes)、列表(lists)、集合(sets)、范围查询的有序集合(sorted sets)、位图(bitmaps)、超日志(hyperloglogs)、地理空间索引(geospatial indexes)、流(streams)等多种类型的数据结构。
Redis内置了复制(replication),LUA脚本(Luascripting)、LRU逐出(LRU eviction),事务(transactions)和不同级别的磁盘持久化(persistence)、并通过Redis哨兵(Sentinel)和自动分区(Cluster)提供高可用性(high availabitity)。

2、下载安装

redis官方下载(仅提供了linux版本):https://download.redis.io/releases/
github下载windows版本:https://github.com/MicrosoftArchive/redis/tags

下载后解压如下:
在这里插入图片描述

启动redis-server.exe

3、redis的常用命令

Redis命令十分丰富,是以数据结构的群组区分,包括的命令组有Cluster、Connection、Geo、Hashes、HyperLogLog、Keys、Lists、Pub/Sub、Scripting、Server、Sets、Sorted Sets、Strings、Transactions一共14个redis命令组两百多个redis命令,您可以通过Redis官方中文网的命令检索页面https://redis.io/commands快速查找命令

4、Springboot集成redis

idea新建springboot项目,
Springboot-Version 2.4.3,
JKD-Version 1.8

引入redis的依赖如下:

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>	

properties配置如下

#配置redis
spring.redis.host=localhost
spring.redis.password=
spring.redis.port=6379

编写测试类
@RestController
public class RedisController {

@Autowired
private RedisTemplate redisTemplate;
@GetMapping("/opsStr")
public String getKey(){
    redisTemplate.setValueSerializer(new StringRedisSerializer());
    redisTemplate.opsForValue().set("test","this is my first redis key");
    return redisTemplate.opsForValue().get("test").toString();
}

}

浏览器访问如下
在这里插入图片描述

此时你已经完成了简单的redis集成,存入了一个key为“test”,value 为“this is my first redis key”的K-V键值数据。

5、redis-config配置密码

虽然已经完成了redis的集成,但是你会发现redis的配置文件中并没有配置用户名和密码,这在实际应用中是十分不安全的,下面通过两种方式为redis设置加密

5.1 命令配置
打开redis的命令访问控制台
在这里插入图片描述

设置认证密码:config set requirepass redis
在这里插入图片描述

5.2 修改redis.window.config文件如下

在这里插入图片描述

6、redis 五种常见数据结构

我们都知道,在 redis 中一共有5种数据结构,那每种数据结构的使用场景都是什么呢?
String——字符串
Hash——字典
List——列表
Set——集合
Sorted Set——有序集合
下面我们就来简单说明一下它们各自的使用场景:

6.1、String——字符串

String 数据结构是简单的 key-value 类型,value 不仅可以是 String,可以完全实现目前 Memcached 的功能,并且效率更高。

java-api:

  set(K key, V value)	新增一个键值对,key为键,value为值 
  get(Object key)	获取指定key对应的值
  append(K key, V value)	在原有值的基础上新增字符串到末尾 
  get(K key, long start, long end)	获取key键所对应value从start位置开始到end位置之间的字符串   
  getAndSet(K key, V value)	获取原来key键所对应的值作为方法返回值,并对该键重新赋值。  
  setBit(K key, long offset,boolean value)	key键对应的值value对应的ascii码,在offset的位置(从左向右数)变为value。
  getBit(K key, long offset)	判断指定的位置ASCII码的bit位是否为1size(K key)	获取指定长度的字符串 Increment(K key, double delta)	以增量的方式将double值存储在变量中。
  Increment(K key, long delta)	以增量的方式将long值存储在变量中。 
  setIfAbsent(K key, V  value)	如果键不存在则新增,存在则不改变已经有的值。 
  set(K key, V value, long timeout, TimeUnit unit)	设置变量值的过期时间。 
  set(K key, V value, long offset)	覆盖从指定位置开始的值。

使用场景:

1. 缓存复杂业务查询的结果集,降低业务代码对 
2. 存放某些全局的常量标识

6.2、Hash——散列

在 Memcached 中,我们经常将一些结构化的信息打包成 hashmap,在客户端序列化后存储为一个字符串的值(一般是 JSON 格式),比如用户的昵称、年龄、性别、积分等。这时候在需要修改其中某一项时,通常需要将字符串(JSON)取出来,然后进行反序列化,修改某一项的值,再序列化成字符串(JSON)存储回去。简单修改一个属性就干这么多事情,消耗必定是很大的,也不适用于一些可能并发操作的场合(比如两个并发的操作都需要修改积分)。而 Redis 的 Hash 结构可以使你像在数据库中 Update 一个属性一样只修改某一项属性值。#p#分页标题#e#

java-api

put(H key, HK hashKey, HV value)	新增hashMap值。
values(H key)	获取指定变量中的hashMap值。
entries(H key)	获取变量中的键值对。
get(H key, Object hashKey)	获取变量中的指定map键是否有值,如果存在该map键则获取值,没有则返回null。
hasKey(H key, Object hashKey)	判断变量中是否有指定的map键。
keys(H key)	获取变量中的键。
size(H key)	获取变量的长度。
increment(H key, HK hashKey, double delta)	使变量中的键以double值的大小进行自增长。
increment(H key, HK hashKey, long delta)	使变量中的键以long值的大小进行自增长。
multiGet(H key, Collection hashKeys)	以集合的方式获取变量中的值。
putAll(H key, Map<? extends HK,? extends HV> m)	以map集合的形式添加键值对。
putIfAbsent(H key, HK hashKey, HV value)	如果变量值存在,在变量中可以添加不存在的的键值对,如果变量不存在,则新增一个变量,同时将键值对添加到该变量。
delete(H key, Object… hashKeys)	删除变量中的键值对,可以传入多个参数,批量删除键值对。

使用场景:

1.存放数据字典
2.存放对象的属性和值,在内存中完成对象的增删改

6.3、List——列表

List 说白了就是链表(redis 使用双端链表实现的 List),相信学过数据结构知识的人都应该能理解其结构。使用 List 结构,我们可以轻松地实现最新消息排行等功能(比如新浪微博的 TimeLine )。List 的另一个应用就是消息队列,可以利用 List 的 *PUSH 操作,将任务存在 List 中,然后工作线程再用 POP 操作将任务取出进行执行。Redis 还提供了操作 List 中某一段元素的 API,你可以直接查询,删除 List 中某一段的元素。

java-api

leftPush(K key, V value)	在集合左边添加元素值。
index(K key, long index)	获取集合指定位置的值。
range(K key, long start, long end)	获取指定区间的值。
leftPush(K key, V pivot, V value)	把最后一个参数值放到指定集合的第一个出现中间参数的前面,如果中间参数值存在的话。
leftPushAll(K key, V… values)	向左边批量添加参数元素。
leftPushAll(K key, Collection values)	以集合的方式向左边批量添加元素。
leftPushIfPresent(K key, V value)	如果存在集合则添加元素。
rightPush(K key, V value)	向集合最右边添加元素。
rightPush(K key, V pivot, V value)	向集合中第一次出现第二个参数变量元素的右边添加第三个参数变量的元素值。
rightPushAll(K key, V… values)	向右边批量添加元素。
rightPushAll(K key, Collection values)	以集合方式向右边添加元素。
rightPushIfPresent(K key, V value)	向已存在的集合中添加元素。
size(K key)	获取集合长度。
leftPop(K key)	移除集合中的左边第一个元素。
leftPop(K key, long timeout, TimeUnit unit)	移除集合中左边的元素在等待的时间里,如果超过等待的时间仍没有元素则退出。
rightPop(K key)	移除集合中右边的元素。
rightPop(K key, long timeout, TimeUnit unit)	移除集合中右边的元素在等待的时间里,如果超过等待的时间仍没有元素则退出。
rightPopAndLeftPush(K sourceKey, K destinationKey)	移除集合中右边的元素,同时在左边加入一个元素。
rightPopAndLeftPush(K sourceKey, K destinationKey, long timeout, TimeUnit unit)	移除集合中右边的元素在等待的时间里,同时在左边添加元素,如果超过等待的时间仍没有元素则退出。
set(K key, long index, V value)	在集合的指定位置插入元素,如果指定位置已有元素,则覆盖,没有则新增,超过集合下标+n则会报错。
remove(K key, long count, Object value)	从存储在键中的列表中删除等于值的元素的第一个计数事件。count> 0:删除等于从左到右移动的值的第一个元素;count< 0:删除等于从右到左移动的值的第一个元素;count = 0:删除等于value的所有元素。
trim(K key, long start, long end) 截取集合元素长度,保留长度内的数据。

使用场景:

1.消息队列:reids的链表结构,可以轻松实现阻塞队列,可以使用左进右出的命令组成来完成队列的设计。比如:数据的生产者可以通过Lpush命令从左边插入数据,多个数据消费者,可以使用BRpop命令阻塞的“抢”列表尾部的数据
2.微信朋友圈下拉刷新,文章列表或者数据分页展示的应用。比如,我们常用的博客网站的文章列表,当用户量越来越多时,而且每一个用户都有自己的文章列表,而且当文章多时,都需要分页展示,这时可以考虑使用redis的列表,列表不但有序同时还支持按照范围内获取元素,可以完美解决分页查询功能。大大提高查询效率。

6.4、Set——集合

Set 就是一个集合,集合的概念就是一堆不重复值的组合。利用 Redis 提供的 Set 数据结构,可以存储一些集合性的数据。比如在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。因为 Redis 非常人性化的为集合提供了求交集、并集、差集等操作,那么就可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。

java-api

add(K key, V… values)	向变量中批量添加值。
members(K key)	获取变量中的值。
size(K key)	获取变量中值的长度。
randomMember(K key)	随机获取变量中的元素。
randomMembers(K key, long count)	随机获取变量中指定个数的元素。
isMember(K key, Object o)	检查给定的元素是否在变量中。
move(K key, V value, K destKey)	转移变量的元素值到目的变量。
pop(K key)	弹出变量中的元素。
remove(K key, Object… values)	批量移除变量中的元素。
scan(K key, ScanOptions options)	匹配获取键值对,ScanOptions.NONE为获取全部键值对;ScanOptions.scanOptions().match(“C”).build()匹配获取键位map1的键值对,不能模糊匹配。
difference(K key, K otherKey)	通过集合求差值。
difference(K key, Collection otherKeys)	通过给定的key求2个set变量的差值。
differenceAndStore(K key, K otherKey, K destKey)	将求出来的差值元素保存。
differenceAndStore(K key, Collection otherKeys, K destKey)	将求出来的差值元素保存。
distinctRandomMembers(K key, long count)	获取去重的随机元素。
intersect(K key, K otherKey)	获取2个变量中的交集。
intersect(K key, Collection otherKeys)	获取多个变量之间的交集。
intersectAndStore(K key, K otherKey, K destKey)	获取2个变量交集后保存到最后一个参数。上。
intersectAndStore(K key, Collection otherKeys, K destKey)	获取多个变量的交集并保存到最后一个参数上。
union(K key, K otherKey)	获取2个变量的合集。
union(K key, Collection otherKeys)	获取多个变量的合集。
unionAndStore(K key, K otherKey, K destKey)	获取2个变量合集后保存到最后一个参数上。
unionAndStore(K key, Collection otherKeys, K destKey)	获取多个变量的合集并保存到最后一个参数上。

使用场景:
1.共同好友、二度好友
2.统计唯一元素
3.好友推荐的时候,根据 tag 求交集,大于某个 threshold 就可以推荐

6.5、Sorted Set——有序集合

和Sets相比,Sorted Sets是将 Set 中的元素增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列,比如一个存储全班同学成绩的 Sorted Sets,其集合 value 可以是同学的学号,而 score 就可以是其考试得分,这样在数据插入集合的时候,就已经进行了天然的排序。另外还可以用 Sorted Sets 来做带权重的队列,比如普通消息的 score 为1,重要消息的 score 为2,然后工作线程可以选择按 score 的倒序来获取工作任务。让重要的任务优先执行。

java-api:

add(K key, V value, double score)	添加元素到变量中同时指定元素的分值。
range(K key, long start, long end)	获取变量指定区间的元素。
rangeByLex(K key, RedisZSetCommands.Range range)	用于获取满足非score的排序取值。这个排序只有在有相同分数的情况下才能使用,如果有不同的分数则返回值不确定。
angeByLex(K key, RedisZSetCommands.Range range, RedisZSetCommands.Limit limit)	用于获取满足非score的设置下标开始的长度排序取值。
add(K key, Set<ZSetOperations.TypedTuple> tuples)	通过TypedTuple方式新增数据。
rangeByScore(K key, double min, double max)	根据设置的score获取区间值。
rangeByScore(K key, double min, double max,long offset, long count)	根据设置的score获取区间值从给定下标和给定长度获取最终值。
rangeWithScores(K key, long start, long end)	获取RedisZSetCommands.Tuples的区间值。
rangeByScoreWithScores(K key, double min, double max)	获取RedisZSetCommands.Tuples的区间值通过分值。
rangeByScoreWithScores(K key, double min, double max, long offset, long count)	获取RedisZSetCommands.Tuples的区间值从给定下标和给定长度获取最终值通过分值。
count(K key, double min, double max)	获取区间值的个数。
rank(K key, Object o)	获取变量中元素的索引,下标开始位置为0scan(K key, ScanOptions options)	匹配获取键值对,ScanOptions.NONE为获取全部键值对;ScanOptions.scanOptions().match(“C”).build()匹配获取键位map1的键值对,不能模糊匹配。
score(K key, Object o)	获取元素的分值。
zCard(K key)	获取变量中元素的个数。
incrementScore(K key, V value, double delta)	修改变量中的元素的分值。
reverseRange(K key, long start, long end)	索引倒序排列指定区间元素。
reverseRangeByScore(K key, double min, double max)	倒序排列指定分值区间元素。
reverseRangeByScore(K key, double min, double max, long offset, long count)	倒序排列从给定下标和给定长度分值区间元素。
reverseRangeByScoreWithScores(K key, double min, double max)	倒序排序获取RedisZSetCommands.Tuples的分值区间值。
reverseRangeByScoreWithScores(K key, double min, double max, long offset, long count)	倒序排序获取RedisZSetCommands.Tuples的从给定下标和给定长度分值区间值。
reverseRangeWithScores(K key, long start, long end)	索引倒序排列区间值。
reverseRank(K key, Object o)	获取倒序排列的索引值。
intersectAndStore(K key, K otherKey, K destKey)	获取2个变量的交集存放到第3个变量里面。
intersectAndStore(K key, Collection otherKeys, K destKey)	获取多个变量的交集存放到第3个变量里面。
unionAndStore(K key, K otherKey, K destKey)	获取2个变量的合集存放到第3个变量里面。
unionAndStore(K key, Collection otherKeys, K destKey)	获取多个变量的合集存放到第3个变量里面。
remove(K key, Object… values)	批量移除元素根据元素值。
removeRangeByScore(K key, double min, double max)	根据分值移除区间元素。
removeRange(K key, long start, long end)	根据索引值移除区间元素。

使用场景:
1.排行榜
2.比较复杂的数据结构,一般用到的场景不算太多

参考博客:https://blog.csdn.net/xiamaocheng/article/details/104050468

7、redis 其他功能使用场景

1. 订阅-发布系统

Pub/Sub 从字面上理解就是发布(Publish)与订阅(Subscribe),在 Redis 中,你可以设定对某一个 key 值进行消息发布及消息订阅,当一个 key 值上进行了消息发布后,所有订阅它的客户端都会收到相应的消息。这一功能最明显的用法就是用作实时消息系统,比如普通的即时聊天,群聊等功能。

2. 事务——Transactions

虽然 Redis 的 Transactions 提供的并不是严格的 ACID 的事务(比如一串用 EXEC 提交执行的命令,在执行中服务器宕机,那么会有一部分命令执行了,剩下的没执行),但是这个 Transactions 还是提供了基本的命令打包执行的功能(在服务器不出问题的情况下,可以保证一连串的命令是顺序在一起执行的,中间有会有其它客户端命令插进来执行)。Redis 还提供了一个 Watch 功能,你可以对一个 key 进行 Watch,然后再执行 Transactions,在这过程中,如果这个 Watched 的值进行了修改,那么这个 Transactions 会发现并拒绝执行。

8、redis持久化

RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储.
AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大.
如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式.
你也可以同时开启两种持久化方式, 在这种情况下,
当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整.

8.1、RDB(默认持久化策略)

1.工作原理:
快照:通过设置让他在N秒内数据集至少有M个改动,自动保存一次数据集,将保存的结果存放在名称为dump.rdb的二级制文件中。你也可以通过SAVE或BGSAVE,手动的让Redis进行数据集的保存操作。

例如:save 60 1000 -->60秒内至少有1000个键改动

2.工作方式:

当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:

Redis 调用forks. 同时拥有父进程和子进程。
子进程将数据集写入到一个临时 RDB 文件中。
当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
3.RDB的优点:

RDB是一个非常紧凑的文件,它保存了某个时间点得数据集,非常适用于数据集的备份,比如你可以在每个小时报保存一下过去24小时内的数据,同时每天保存过去30天的数据,这样即使出了问题你也可以根据需求恢复到不同版本的数据集.
RDB是一个紧凑的单一文件,很方便传送到另一个远端数据中心或者亚马逊的S3(可能加密),非常适用于灾难恢复.
RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能.
与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些.
4.RDB的缺点

如果你希望在redis意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么RDB不适合你.虽然你可以配置不同的save时间点(例如每隔5分钟并且对数据集有100个写的操作),是Redis要完整的保存整个数据集是一个比较繁重的工作,你通常会每隔5分钟或者更久做一次完整的保存,万一在Redis意外宕机,你可能会丢失几分钟的数据.
RDB需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求.如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续1秒,AOF也需要fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度.

8.2、AOF

1.工作原理:

AOF 重写和 RDB 创建快照一样,都巧妙地利用了写时复制机制:

Redis 执行 fork() ,现在同时拥有父进程和子进程。
子进程开始将新 AOF 文件的内容写入到临时文件。
对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF文件的末尾,这样样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。
当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。
现在 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾

打开AOF方式:appendonly yes

AOF持久化策略

每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全
每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。
从不 fsync :将数据交给操作系统来处理。更快,也更不安全的选择。 推荐(并且也是默认)的措施为每秒 fsync 一次, 这种
fsync 策略可以兼顾速度和安全性。
2.工作方式:日志重写

因为 AOF 的运作方式是不断地将命令追加到文件的末尾, 所以随着写入命令的不断增加, AOF 文件的体积也会变得越来越大。举个例子,如果你对一个计数器调用了 100 次 INCR , 那么仅仅是为了保存这个计数器的当前值, AOF 文件就需要使用 100条记录(entry)。然而在实际上, 只使用一条 SET 命令已经足以保存计数器的当前值了, 其余 99 条记录实际上都是多余的。

为了处理这种情况, Redis 支持一种有趣的特性: 可以在不打断服务客户端的情况下, 对 AOF 文件进行重建(rebuild)。执行BGREWRITEAOF 命令, Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集所需的最少命令。

Redis 2.2 需要自己手动执行 BGREWRITEAOF 命令;
Redis 2.4 则可以自动触发 AOF 重写

3、AOF优点:

使用AOF 会让你的Redis更加耐久:
你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync.使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据.
AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题.
Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子,如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。
4、AOF 缺点

对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快,即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)

8.3、如何选择持久化方式

一般来说, 如果想达到足以媲美 PostgreSQL 的数据安全性, 你应该同时使用两种持久化功能。

如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。

有很多用户都只使用 AOF 持久化, 但我们并不推荐这种方式: 因为定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快, 除此之外, 使用 RDB 还可以避免之前提到的 AOF 程序的 bug 。

8.4、备份数据

当服务器要创建一个新的 RDB 文件时, 它先将文件的内容保存在一个临时文件里面, 当临时文件写入完毕时, 程序才使用 rename(2) 原子地用临时文件替换原来的 RDB 文件。

这也就是说, 无论何时, 复制 RDB 文件都是绝对安全的。

创建一个定期任务(cron job), 每小时将一个 RDB 文件备份到一个文件夹, 并且每天将一个 RDB 文件备份到另一个文件夹。
确保快照的备份都带有相应的日期和时间信息, 每次执行定期任务脚本时, 使用 find 命令来删除过期的快照: 比如说, 你可以保留最近
48 小时内的每小时快照, 还可以保留最近一两个月的每日快照。
至少每天一次, 将 RDB 备份到你的数据中心之外, 或者至少是备份到你运行 Redis 服务器的物理机器之外。

8.5、容灾备份

Redis 的容灾备份基本上就是对数据进行备份, 并将这些备份传送到多个不同的外部数据中心。容灾备份可以在 Redis 运行并产生快照的主数据中心发生严重的问题时, 仍然让数据处于安全状态。

因为很多 Redis 用户都是创业者, 他们没有大把大把的钱可以浪费, 所以下面介绍的都是一些实用又便宜的容灾备份方法:

Amazon S3 ,以及其他类似 S3 的服务,是一个构建灾难备份系统的好地方。 最简单的方法就是将你的每小时或者每日 RDB备份加密并传送到 S3 。 对数据的加密可以通过 gpg -c 命令来完成(对称加密模式)。 记得把你的密码放到几个不同的、安全的地方去(比如你可以把密码复制给你组织里最重要的人物)。 同时使用多个储存服务来保存数据文件,可以提升数据的安全性。
传送快照可以使用 SCP 来完成(SSH 的组件)。 以下是简单并且安全的传送方法: 买一个离你的数据中心非常远的 VPS , 装上SSH , 创建一个无口令的 SSH 客户端 key , 并将这个 key 添加到 VPS 的 authorized_keys 文件中,这样就可以向这个 VPS 传送快照备份文件了。 为了达到最好的数据安全性,至少要从两个不同的提供商那里各购买一个 VPS来进行数据容灾备份。
需要注意的是, 这类容灾系统如果没有小心地进行处理的话, 是很容易失效的。最低限度下, 你应该在文件传送完毕之后,检查所传送备份文件的体积和原始快照文件的体积是否相同。 如果你使用的是 VPS , 那么还可以通过比对文件的 SHA1校验和来确认文件是否传送完整。

9、redis集群的三种方式

redis有三种集群方式:主从复制,哨兵模式和Cluster集群。

9.1、主从复制(读写分离)

读写分离,降低主服务查询负载
在这里插入图片描述

主从复制原理
当一个master服务器与一个slave服务器链接后,slave服务器会对master服务器发起同步请求。master服务器会根据请求中的replicationId和offset计算出所需要的增量数据集,将数据流发送给slave进行同步,若主服务器不能识别slave服务器发来的replicaiotnId和offset会对当前的数据进行全量同步。

主从复制优缺点:
优点

  • 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离
  • 为了分载Master的读操作压力,Slave服务器可以为客户端提供只读操作的服务,写服务仍然必须由Master来完成
  • Slave同样可以接受其它Slaves的连接和同步请求,这样可以有效的分载Master的同步压力。 Master
  • Server是以非阻塞的方式为Slaves提供服务。所以在Master-Slave同步期间,客户端仍然可以提交查询或修改请求。 Slave
  • Server同样是以非阻塞的方式完成数据同步。在同步期间,如果有客户端提交查询请求,Redis则返回同步之前的数据

缺点:

  • 若master服务器未做持久化配置,服务重启后slave服务器将会同步master服务器的清空状态,造成主从服务器的数据都丢失。
  • Redis不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的IP才能恢复。
  • 主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性。
  • Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。

9.2、哨兵模式(高可用)

故障转移,服务恢复。主观下线,客观下线
在这里插入图片描述

当主服务器中断服务后,可以将一个从服务器升级为主服务器,以便继续提供服务,但是这个过程需要人工手动来操作。 为此,Redis 2.8中提供了哨兵工具来实现自动化的系统监控和故障恢复功能。
哨兵的作用就是监控Redis系统的运行状况。它的功能包括以下两个。
(1)监控主服务器和从服务器是否正常运行。
(2)主服务器出现故障时自动将从服务器转换为主服务器。

哨兵的工作方式:

  • 每个Sentinel(哨兵)进程以每秒钟一次的频率向整个集群中的Master主服务器,Slave从服务器以及其他Sentinel(哨兵)进程发送一个 PING 命令。
  • 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel(哨兵)进程标记为主观下线(SDOWN)
  • 如果一个Master主服务器被标记为主观下线(SDOWN),则正在监视这个Master主服务器的所有 Sentinel(哨兵)进程要以每秒一次的频率确认Master主服务器的确进入了主观下线状态
  • 当有足够数量的 Sentinel(哨兵)进程(大于等于配置文件指定的值)在指定的时间范围内确认Master主服务器进入了主观下线状态(SDOWN), 则Master主服务器会被标记为客观下线(ODOWN)
  • 在一般情况下, 每个 Sentinel(哨兵)进程会以每 10 秒一次的频率向集群中的所有Master主服务器、Slave从服务器发送 INFO 命令。
  • 当Master主服务器被 Sentinel(哨兵)进程标记为客观下线(ODOWN)时,Sentinel(哨兵)进程向下线的 Master主服务器的所有 Slave从服务器发送 INFO 命令的频率会从 10 秒一次改为每秒一次。
  • 若没有足够数量的 Sentinel(哨兵)进程同意 Master主服务器下线, Master主服务器的客观下线状态就会被移除。若 Master主服务器重新向 Sentinel(哨兵)进程发送 PING 命令返回有效回复,Master主服务器的主观下线状态就会被移除。

哨兵模式的优缺点
优点:

  • 哨兵模式是基于主从模式的,所有主从的优点,哨兵模式都具有。
  • 主从可以自动切换,系统更健壮,可用性更高。
    缺点:
  • Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。

9.3、Cluster集群(可扩展,省内存)

一致性哈希,分布插槽,
在这里插入图片描述

redis的哨兵模式基本已经可以实现高可用,读写分离 ,但是在这种模式下每台redis服务器都存储相同的数据,很浪费内存,所以在redis3.0上加入了cluster模式,实现的redis的分布式存储,也就是说每台redis节点上存储不同的内容。
Redis-Cluster采用无中心结构,它的特点如下:

  • 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
  • 节点的fail是通过集群中超过半数的节点检测失效时才生效。
  • 客户端与redis节点直连,不需要中间代理层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
    工作方式
    在redis的每一个节点上,都有这么两个东西,一个是插槽(slot),它的的取值范围是:0-16383。还有一个就是cluster,可以理解为是一个集群管理的插件。当我们的存取的key到达的时候,redis会根据crc16的算法得出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。
    为了保证高可用,redis-cluster集群引入了主从模式,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点。当其它主节点ping一个主节点A时,如果半数以上的主节点与A通信超时,那么认为主节点A宕机了。如果主节点A和它的从节点A1都宕机了,那么该集群就无法再提供服务了。
  • 26
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值