Redis学习笔记

本文介绍了MySQL数据库在高并发场景下遇到的挑战,引出NoSQL数据库的重要性,特别是Redis的使用。文章详细讲解了Redis的起源、特点、功能、与其他缓存产品的区别,以及在大数据、高并发、多样数据类型下的应用场景。文中还涵盖了Redis的多种数据结构,持久化机制(RDB和AOF)以及主从复制的概念和工作流程,最后提到了Redis在实际开发中的使用和配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NoSQL入门概述

MySQL数据库应用历史

单机MySQL的美好年代

在90年代,一个网站的访问量一般都不大,用单个数据库完全可以轻松应付。那个时候更多的是静态页面,动态交互型的网站不多。

aHR0cHM6Ly9naXRlZS5jb20vamFsbGVua3dvbmcvTGVhcm5SZWRpcy9yYXcvbWFzdGVyL2ltYWdlLzAxLnBuZw

DAL:是数据库访问的英文缩写,即为数据库访问层(Data Access Layer)

上述架构下,我们来看看数据库存储的瓶颈是什么?

  • 数据量的总大小一个机器放不下时
  • 数据的索引(B+ Tree)一个机器的内存放不下时
  • 访问量(读写混合)一个实例不能承受
Memcached(缓存) + MySQL + 垂直拆分

后来,随着访问量的上升,几乎大部分使用MySQL架构的网站在数据库上都出现了性能问题,web程序不再仅仅专注在功能上,同时也在追求性能。程序员们开始大量的使用缓存技术来缓解数据库的压力,优化数据库的结构和索引。开始比较流行的是通过文件缓存来缓解数据库压力,但是当访问量继续增大的时候,多台web机器通过文件缓存不能共享,大量的小文件缓存也带来了比较高的IO压力。在这个时候,Memcached就自然的成为一个非常时尚的技术产品。

aHR0cHM6Ly9naXRlZS5jb20vamFsbGVua3dvbmcvTGVhcm5SZWRpcy9yYXcvbWFzdGVyL2ltYWdlLzAyLnBuZw

MySQL主从读写分离

由于数据库的写入压力增加,Memcached只能缓解数据库的读取压力。读写集中在一个数据库上让数据库不堪重负,大部分网站开始使用主从复制技术来达到读写分离,以提高读写性能和读库的可拓展性。MySQL的master-slave模式成为这个时候的网站标配了。

aHR0cHM6Ly9naXRlZS5jb20vamFsbGVua3dvbmcvTGVhcm5SZWRpcy9yYXcvbWFzdGVyL2ltYWdlLzAzLnBuZw

分表分库 + 水平拆分 + MySQL集群

在Memcached的高速缓存,MySQL的主从复制,读写分离的基础之上,这时MySQL主库的写压力开始出现瓶颈,而数据量的持续猛增,由于MyISAM使用表锁,在高并发下会出现严重的锁问题,大量的高并发MySQL应用开始使用InnoDB引擎替代MyISAM。

同时,开始流行使用分表分库来缓解写压力和数据库增长的拓展问题。这个时候,分库分表成了一个热门技术,是面试的热门问题也是业界讨论的热门的技术问题。也就是在这个时候,MySQL推出了还不太稳定的表分区,这也给技术实力一般的公司带来了希望。虽然MySQL推出了MySQL Cluster集群,但性能也不能很好的满足互联网的要求,只是在高可靠性上提供了非常大的保证。

aHR0cHM6Ly9naXRlZS5jb20vamFsbGVua3dvbmcvTGVhcm5SZWRpcy9yYXcvbWFzdGVyL2ltYWdlLzA0LnBuZw

MySQL的拓展性瓶颈

MySQL数据库也经常存储一些大文本字段,导致数据库表非常大,在做数据库恢复的时候就导致非常的慢,不容易快速恢复数据库。比如1000万4KB大小的文件就接近40GB的大小,如果能把这些数据从MySQL中省去,MySQL将变得非常的小。关系数据库很强大,但是它并不能很好的应付所有的应用场景。MySQL的拓展性差(需要复杂的技术来实现),大数据下IO压力大,表结构更改困难,正视当前使用MySQL的开发人员面临的问题。

今天是什么样子?

aHR0cHM6Ly9naXRlZS5jb20vamFsbGVua3dvbmcvTGVhcm5SZWRpcy9yYXcvbWFzdGVyL2ltYWdlLzA1LnBuZw

NoSQL基础概念

为什么使用NoSQL

今天我们可以通过第三方平台(如Google、Facebook)可以很容易的访问和抓取数据。用户的个人信息、社交网络、地理位置,用户生成的数据和用户操作日志已经成倍的增加。我们如果要对这些用户数据进行挖掘,那MySQL数据库已经不适合这些应用了,NoSQL数据库的发展能很好的处理这些大的数据。

NoSQL是什么

NoSQL(Not Only SQL),意思是不仅仅是SQL,泛指非关系型数据库。

NoSQL能干嘛

易拓展

​ NoSQL数据库种类繁多,但是一个共同的特点都是去掉关系数据库的关系型特性。数据之间无关系,这样就非常容易拓展。也无形之间,在架构的层面上带来了可拓展的能力。

大数据量高性能

​ NoSQL数据库都具有非常高的读写性能,尤其在大数据量下,同样表现优秀。这得益于它的无关系性,数据库的结构简单。

​ 一般MySQL使用Query Cache,每次表的更新Cache就失效,是一种大粒度的Cache,在针对web2.0的交互频繁的应用,Cache性能不高。

​ 而NoSQL的Cache是记录级的,是一种细粒度的Cache,所以NoSQL在这个层面上来说就要性能高很多了。

多样灵活的数据类型

​ NoSQL无需事先为要存储的数据建立字段,随时可以存储自定义的数据格式。

​ 而在关系数据库里,增删字段是一件非常麻烦的事情,如果是非常大数据量的表,增加字段简直就是一个噩梦。

传统RDBMS VS NOSQL

RDBMS

  • 高度组织化结构化数据
  • 结构化查询寓言(SQL)
  • 数据和关系都存储在单独的表中
  • 数据操纵寓言,数据定义寓言
  • 严格的一致性
  • 基础事务

NoSQL

  • 代表着不仅仅是SQL
  • 没有生命性查询寓言
  • 没有预定义的模式
  • 键-值对存储,列存储,文档存储,图形数据库
  • 最终一致性,而非ACID属性
  • 非结构化和不可预知的数据
  • CAP定理
  • 高性能、高可用性和可拓展性
有哪些NoSQL
  • Redis
  • Memcached
  • MongDB
怎么用
  • Key - Value
  • Cache
  • Persistence
3V + 3高

大数据时代的3V

  1. 海量Volume
  2. 多样Variety
  3. 实时Velocity

互联网需求的3高

  1. 高并发
  2. 高可拓展
  3. 高性能

当下NoSQL应用场景简介

Alibaba中文站商品信息如何存放

架构发展历程

  1. 演变过程(到第四代为止)

    aHR0cHM6Ly9naXRlZS5jb20vamFsbGVua3dvbmcvTGVhcm5SZWRpcy9yYXcvbWFzdGVyL2ltYWdlLzA4LnBuZw

  2. 第四代网站主要解决了哪些问题

    WechatIMG22

  3. 第五代架构使命

    aHR0cHM6Ly9naXRlZS5jb20vamFsbGVua3dvbmcvTGVhcm5SZWRpcy9yYXcvbWFzdGVyL2ltYWdlLzEwLnBuZw

  4. 和我们相关的,多数据源类型的存储问题,针对不同的数据使用不同的数据库

    aHR0cHM6Ly9naXRlZS5jb20vamFsbGVua3dvbmcvTGVhcm5SZWRpcy9yYXcvbWFzdGVyL2ltYWdlLzExLnBuZw

商品信息的存储方案,以阿里巴巴中文网站首页为例

  1. 商品基本信息

    名称、价格、出厂日期,生产厂商等。

    关系型数据库,mysql/oracle目前淘宝在去Oracle化,套餐使用的MySQL是自己改造过的,不是我们平常用的MySQL。

    为什么去IOE(在IT建设过程中,去除IBM小型机、Oracle数据库一级EMC存储设备)简而意之,可以不受这些东西约束。

  2. 商品描述、详情、评价信息(多文字类)

    文档数据库MongDB

  3. 商品的图片

    分布式的文件系统中(淘宝自家的TFS、Google的GFS、Hadoop的HDFS)

  4. 商品的关键字

    淘宝自己的ISearch

  5. 商品的波段性的热点高频信息(如情人节的巧克力)

    内存数据库(Redis、Tair、Memcache)

  6. 商品的交易、价格计算、积分累计

    支付宝和外部第三方支付接口

大型互联网应用(大数据、高并发、多样数据类型)的难点和解决方案

难点

  • 数据类型多样性
  • 数据源多样性和变化重构
  • 数据源改造而数据服务平台不需要大面积重构

解决办法

  • EAI

  • USDL统一数据平台服务层

    • 是什么

      aHR0cHM6Ly9naXRlZS5jb20vamFsbGVua3dvbmcvTGVhcm5SZWRpcy9yYXcvbWFzdGVyL2ltYWdlLzEyLnBuZw

    • 什么样

      aHR0cHM6Ly9naXRlZS5jb20vamFsbGVua3dvbmcvTGVhcm5SZWRpcy9yYXcvbWFzdGVyL2ltYWdlLzEzLnBuZw

    • 映射

      aHR0cHM6Ly9naXRlZS5jb20vamFsbGVua3dvbmcvTGVhcm5SZWRpcy9yYXcvbWFzdGVyL2ltYWdlLzE0LnBuZw

    • API

      2021033001

    • 热点缓存

      2021033002

NoSQL数据库的四大分类

KV

  • 新浪:BerkeleyDB + Redis
  • 美团:Redis + tair
  • 阿里、百度:memcache + Redis

文档型数据库(bson格式比较多)

  • CouchDB

  • MongDB

    MongDB是一个机遇分布式文件存储的数据库。由C++寓言编写,旨在为WEB应用提供可拓展的高性能数据存储解决方案。

    MongDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富的,最像关系数据库的。

列储存数据库

  • HBase
  • Cassandra
  • 分布式文件系统

图关系数据库

它不是放图形的、放的是关系,比如:朋友圈社交网络、广告推荐系统。

社交网络、推荐系统。专注于构建关系图谱。

Neo4j、InfoGrid

四者对比

2021033003

分布式数据库CAP原理

传统的ACID分别是什么

A(Atomicity)原子性:事务里的所有操作要么全部做完,要么都不做,事务成功的条件是事务里的所有操作成功,只要有一个操作失败,整个事务就失败,需要回滚。

C(Consistency)一致性:数据库要一直处于一致的状态,事务的运行不会改变数据库原本的一致性约束。

I(Isolation)独立性:所谓的独立性是指并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另一个事务修改,只要另外一个事务未提交,它所访问的数据就不受未提交事务的影响。

D(Durability)持久性:持久性是指一旦事务提交后,它所做的修改将会永久的保存在数据库上,即使出现宕机也不会丢失。

CAP
  • C:Consistency(强一致性)
  • A:Availability(可用性)
  • P:Partition tolerance(分区容错性)

CAP理论就是说在分布式存储系统中,最多只能事项上面的两点。

而由于当前的网络硬件肯定会出现延迟丢包等问题,所以分区容忍性是我们必须要实现的。所以我们只能在一致性和可用性之间进行权衡,没有NoSQL系统能同时保证这三点。

  • CA 传统Oracle数据库
  • AP 大多数网站架构的选择
  • CP Redis、MongoDB

一致性和可用性之间抉择

  • 大多数web应用,其实并不需要强一致性。因此牺牲 C换取P,这是目前分布式数据库产品的方向
  • 数据库事务一致性需求:很多web实时系统并不要求严格的数据库事务,对读一致性的要求很低,有些场合对写一致性要求不高,允许实现最终一致性。
经典CAP图

CAP理论的核心是:一个分布式系统不能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。

因此,根据CAP原理将NoSQL数据库分成了满足CA原则、CP原则和AP原则三大类:

  • CA - 单点集群,满足一致性,可用性的系统,通常在可拓展性商不太强大。
  • CP - 满足一致性,分区容忍必的系统,通常性能不是特别高
  • AP - 满足可用性,分区容忍性的系统,通常对一致性要求低一些202

2021033004

BASE

BASE就是为了解决关系数据库强一致性引起的问题而引起的可用性降低而提出的解决方案。

BASE其实是下面三个术语的缩写:

  • 基本可用 Basically Avaliable
  • 软状态 Soft state
  • 最终一致 Eventually consistent

它的思想是通过让系统放松对某一时刻的要求来换取系统整体伸缩性和性能上改观。大型系统旺旺由于地域分布和极高性能的要求,不可能采用分布式事务来完成这些指标,要想获得这些指标,我们必须采用另外一种方式来完成,这里BASE就是解决这个问题的办法。

分布式 + 集群简介
  • 分布式:不同的多台服务器上面部署不同的服务模块,他们之间通过RPC/RMI之间通信和调用,对外提供服务和组内协作。
  • 集群:不同的多台服务器上面部署相同的服务模块,哦通过分布式调度软件进行统一的调度,对外提供服务和访问。

Redis基本概念

定义

REmote Dlctionary Server(远程字段服务器)是完全开源免费的,用C语言编写的,遵循BSD协议,是一个高性能的(key/value)分布式内存数据库,寄予内存运行,并支持持久化的NoSQL数据库,是当前最热门的NoSQL数据库之一,也被人们称为数据结构服务器。

Redis与其它key-value缓存产品比有以下三个特点
  • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行
  • 不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储
  • 支持数据的备份,即master-slave模式的数据备份
能干嘛
  • 内存存储和持久化:redis支持异步将内存中的数据写到硬盘上,同时不影响继续服务
  • 取最新N个数据的操作,如:可以将最新的10条评论的ID放在Redis的List集合里面
  • 模拟类似于HttpSession这种需要设定过期时间的功能
  • 发布、订阅消息系统
  • 定时器、计数器
怎么玩
  • 数据类型、基本操作和配置
  • 持久化和赋值,RDB/AOF
  • 事务的控制
  • 赋值(主从关系)

Redis 使用

redis基础知识

redis文件介绍

redis-server redis服务器
redis-cli redis命令行客户端
redis-benchmark redis性能测试工具
redis-check-aof aof文件修复工具
redis-check-dump rdb文件检查工具

redis在mac的目录地址

/usr/local/Cellar/redis/6.2.1/bin

redis.conf redis配置文件所在地

/usr/local/etc

启动redis

./redis-server

停止redis

redis-cli shutdown

进入redis

redis-cli

启动后杂项启动知识

  • 单进程

    单进程模型来处理客户端的请求。对读写事件的响应,是通过对epoll函数的包装来做到的。Redis的实际处理速度完全依赖主进程的执行效率。

    Epoll是Linux内核为处理大批量文件描述符而做了改进的epoll,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。

  • 默认16个数据库,类似数组下标从零开始,初始默认使用零号库,可在配置文件配置

  • select 命令切换数据库

  • dbsize 查看当前数据库的key的数量

  • flushdb 清空当前库

  • flushall 清空所有库

  • 统一密码管理,16个库都是同样密码,要么都OK要么一个也连接不上

  • Redis索引都是从零开始

  • 默认端口号是6379,可在redis.conf中修改

  • 哪里去获得redis常见数据类型操作命令

    Redis命令参考

    Redis官网命令参考

Redis常用命令

key关键字
  • Key * :查看当前库所有的key

  • exists key的名字,判断某个key是否存在

    eg : exists hello

    存在返回:(integer) 1

    不存在返回:(integer) 0

  • move key db 将当前数据库的key移动到给定的数据库db当中

    move key的名字 db数据库序号 eg:move hello 15

  • expire key的名字 秒钟:为给定的key设置过期时间

  • ttl key 查看key还有多少秒过期,-1表示永不过期,-2表示已过期

  • type key 查看你的key是什么类型

  • del key 在key存在时删除key

String
  • set key value 设置指定key的值

  • get key 获取指定key的值

  • getset key value 将给定key的值设为value,并返回key的就值(old value),不存在则返回nil

  • mget key1 [key2…] 获取所有(一个或多个)给定key的值

  • setnx key value 只有key不存在时设置key的值

  • stelen key value 返回key所存储的字符串值得长度

  • meset key value [key value] 同时设置一个或多个key-value对

  • mesetnx key value [key value] 同时设置一个或多个key-value对,当且仅当所有给定key都不存在

  • incr/decr/incrby/decrby 数字的加减操作,仅当字符串为数字时才支持

    eg:

    ​ Incr li :key(li)对应的value固定加一

    ​ decr li :key(li)对应的value固定减一

    ​ incrby li 5 :key(li)对应的value固定加5

    ​ decrby li 5 :key(li)对应的value固定减5

List

设置值

  • rpush key value1 [value2] 在列表中添加一个或多个值
  • rpushx key value 为已存在的列表添加值
  • lset key index value 通过索引设置列表元素的值
  • lpush key value1 [value2] 将一个或多个值插入到列表头部
  • lpushx key value 将一个值插入到已存在的列表头部
  • linsert key before/alter pivot value 在列表元素前或后插入元素

拿到值

  • lpop key 移出并获取列表的第一个元素

  • rpop key 移出列表的最后一个元素,返回值为移出的元素

  • lindex key index 通过索引获取列表中的元素

  • blpop key1 [key2] timeout 移除并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止

  • brpop key1 [key2] timeout 移出并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止

  • lrange key start stop 获取列表指定范围内的元素

  • llen key 获取列表长度

实例测试

20210401152618

20210401152654

20210401152713

20210401152729

Set
  • sadd key member1 [member2] 向集合添加一个或多个成员
  • scard key 获取集合的成员数
  • sismember key member 判断member元素是否是集合key的成员
  • smembers key 返回集合中的所有成员
  • spop key 移出并返回集合中的一个随机元素
  • srandmemeber key [count] 获取集合中一个或多个随机数
  • srem key member1 [member2] 移出集合中一个或多个成员

使用实例

20210401154046

Hash

K模式不变,但V是一个键值对

常用命令:

  • hdel key field1 [field2] 删除一个或多个哈希表字段
  • hexists key field 查看哈希表key中,指定的字段是否存在
  • hget key field 获取存储在哈希表中指定的字段的值
  • hgetall key 获取在哈希表中指定key的所有字段和值
  • hkeys key 获取所有哈希表中的字段
  • hlen key 获取哈希表中字段的数量
  • hmget key field1 [field2] 获取所有给定字段的值
  • hmset key field1 value1 [field2 value2] 同时将多个field-value(域-值)对设置到哈希表key中
  • hset key field value 将哈希表key中的字段的值设置为value
  • hsetnx key field value 只有在字段field不存在时,设置哈希表字段的值
  • hvals key 获取哈希表中所有值

使用实例:

20210401155747

20210401155810

ZSet

如有需要,再拓展,暂时不做了解

Redis配置文件

#  redis启动命令
# ./redis-server /path/to/redis.conf


#  redis的单位对应的字节数,单位不区分大小写
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
#

#  include表示redis可以包含其他redis的配置文件
################################## INCLUDES ###################################


# include /path/to/local.conf
# include /path/to/other.conf

#启动时加载模块,如果server无法加载模块,则此配置会被忽略。可以使用多个loadmodule。
################################## MODULES #####################################

#
# loadmodule /path/to/my_module.so
# loadmodule /path/to/other_module.so

# 绑定网络接口 监听客户端连接
################################## NETWORK #####################################

#
# Examples:
#
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1 ::1
#

# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES
# JUST COMMENT THE FOLLOWING LINE.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bind 127.0.0.1



# 默认端口号 6379
port 6379

# TCP listen() backlog.
#
# 
tcp-backlog 511


# Close the connection after a client is idle for N seconds (0 to disable)
timeout 0

# TCP keepalive.
#
# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence
# of communication. This is useful for two reasons:
#
# 1) Detect dead peers.
# 2) Take the connection alive from the point of view of network
#    equipment in the middle.
#
# On Linux, the specified value (in seconds) is the period used to send ACKs.
# Note that to close the connection the double of the time is needed.
# On other kernels the period depends on the kernel configuration.
#
# A reasonable value for this option is 300 seconds, which is the new
# Redis default starting with Redis 3.2.1.
tcp-keepalive 300

################################# GENERAL #####################################
# daemonize : 守护进程
# 指定redis是否要用守护线程的方式启动.
# 设置成yes时,代表开启守护进程模式。在该模式下,redis会在后台运行,并将进程pid号写入至redis.conf选项pidfile设置的文件中,此时redis将一直运行,除非手动kill该进程
# 设置成no时,当前界面将进入redis的命令行界面,exit强制退出或者关闭连接工具(putty,xshell等)都会导致redis进程退出。
daemonize yes

#可以通过upstart和systemd管理Redis守护进程
#选项:
#   supervised no - 没有监督互动
#   supervised upstart - 通过将Redis置于SIGSTOP模式来启动信号
#   supervised systemd - signal systemd将READY = 1写入$ NOTIFY_SOCKET
#   supervised auto - 检测upstart或systemd方法基于 UPSTART_JOB或NOTIFY_SOCKET环境变量
# Note: these supervision methods only signal "process is ready."
#       They do not enable continuous liveness pings back to your supervisor.
supervised no

# 配置PID文件路径,当redis作为守护进程运行时,会把PID写到/var/run/redis_6379.pid中
pidfile /var/run/redis_6379.pid

# 定义日志级别
# 参数如下:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel notice

# 输出日志,默认为标准输出,即输出到屏幕上
# output for logging but daemonize, logs will be sent to /dev/null
logfile ""

# 设置日志记录,如果想把它记录到系统日志,就改成 yes
# syslog-enabled no

# 设置系统日志的ID.
# syslog-ident redis

# 指定系统日志设置. Must be USER or between LOCAL0-LOCAL7.是local 不是loca + 10
# syslog-facility local0

# 数据库的数量,默认为16
databases 16

# 是否总显示logo.
always-show-logo yes

#快照配置
################################ SNAPSHOTTING  ################################
#
#保存数据到磁盘:
#
#   save <seconds> <changes>
#
#   Will save the DB if both the given number of seconds and the given
#   number of write operations against the DB occurred.
#
#   In the example below the behaviour will be to save:
#   
#   15分钟有一个key发生变化就保存数据到磁盘
#   after 900 sec (15 min) if at least 1 key changed
#   
#   5分钟有10个key发生变化就保存数据到磁盘
#   after 300 sec (5 min) if at least 10 keys changed
#
#   1分钟有10000个key发生变化就保存数据到磁盘
#   after 60 sec if at least 10000 keys changed
#
#   Note: you can disable saving completely by commenting out all "save" lines.
#
#   还可以删除所有以前配置的保存。
#   通过添加带有单个空字符串参数的保存指令
#   like in the following example:
#
#   save ""

save 900 1
save 300 10
save 60 10000

# 持久化出现错误后,是否依然进行继续进行工作
stop-writes-on-bgsave-error yes

# 是否校验rdb文件,
# 更有利于文件的容错性,但是在保存rdb文件的时候,会有大概10%的性能损耗,
# 所以如果你追求高性能,可以关闭该配置
rdbcompression yes

# 使用压缩rdb文件,rdb文件压缩使用LZF压缩算法,
# yes:压缩,但是需要一些cpu的消耗。
# no:不压缩,需要更多的磁盘空间
rdbchecksum yes

# DB文件名称
dbfilename dump.rdb

# 工作目录.
# DB将在这个目录中写入,指定使用上面的“dbfilename配置指令的文件名
dir ./

#主从复制配置
################################# REPLICATION #################################

# 主从复制。使用 slaveof 做一个redis实例备份另一个redis服务器
#
# 1) Redis复制是异步的, but you can configure a master to
#    stop accepting writes if it appears to be not connected with at least
#    a given number of slaves.
# 2) Redis slaves are able to perform a partial resynchronization with the
#    master if the replication link is lost for a relatively small amount of
#    time. You may want to configure the replication backlog size (see the next
#    sections of this file) with a sensible value depending on your needs.
# 3) Replication is automatic and does not need user intervention. After a
#    network partition slaves automatically try to reconnect to masters
#    and resynchronize with them.
#
# slaveof <masterip> <masterport>


# 配置master的密码,这样可以在连上master后进行认证
# masterauth <master-password>

# 当从节点失去连接或者复制正在进行,从节点有2种运行方式:
#
# yes: 继续响应客户端的请求
# no: 除去INFO和SLAVEOF命令之外的任何请求都会返回一个错误
#
slave-serve-stale-data yes

# 从服务器是否只读
slave-read-only yes

#目前redis复制提供两种方式,disk和socket。
#如果新的slave连上来或者重连的slave无法部分同步,就会执行全量同步,master会生成rdb文件。
# 有2种方式:
# Disk-backed:master创建一个新的进程把rdb文件保存到磁盘,再把磁盘上的rdb文件传递给slave。
# Diskless: master创建一个新的进程,直接把rdb文件以socket的方式发给slave
disk方式的时候,当一个rdb保存的过程中,多个slave都能共享这个rdb文件。socket的方式就的一个个slave顺序复制。在磁盘速度缓慢,网速快的情况下推荐用socket方式

# With slow disks and fast (large bandwidth) networks, diskless replication
# works better.
repl-diskless-sync no

# 当使用socket复制数据启用的时候,socket复制的延迟时间,如果设置成0表示禁用,默认值是5.
repl-diskless-sync-delay 5

# 从节点根据指定的时间间隔向主节点发起ping请求 The default value is 10 seconds.
# repl-ping-slave-period 10

# The following option sets the replication timeout for:
#
# 1) Bulk transfer I/O during SYNC, from the point of view of slave.
# 2) Master timeout from the point of view of slaves (data, pings).
# 3) Slave timeout from the point of view of masters (REPLCONF ACK pings).
#
# It is important to make sure that this value is greater than the value
# specified for repl-ping-slave-period otherwise a timeout will be detected
# every time there is low traffic between the master and the slave.
#复制连接超时时间
# repl-timeout 60

#是否禁止复制tcp链接的tcp nodelay参数,可传递yes或者no。默认是no
#即使用tcp nodelay。如果master设置了yes来禁止tcp nodelay设置,
#在把数据复制给slave的时候,会减少包的数量和更小的网络带宽。
#但是这也可能带来数据的延迟。默认我们推荐更小的延迟,
#但是在数据量传输很大的场景下,建议选择yes
repl-disable-tcp-nodelay no

# Set the replication backlog size. 
#保存复制的命令。
#当从节点在一段时间内断开连接时,主节点会收集数据到backlog这个缓冲区,
#因此当一个从节点想要重新连接时,通常不需要完全的重新同步,
#但是部分的重新同步就足够了,只是通过在断开连接的时候传递数据的一部分。默认是1mb
#
# repl-backlog-size 1mb

# 当主节点不再联系从节点,则释放backlog(内存)
#
# repl-backlog-ttl 3600

# 当master不可用,Sentinel会根据slave的优先级选举一个master。
# 最低的优先级的slave,当选master。而配置成0,永远不会被选举.
#
# By default the priority is 100.
slave-priority 100

# 当健康的slave的个数小于N,matser就禁止写入
# min-slaves-to-write 3
# 延迟小于min-slaves-max-lag秒的slave才认为是健康的slave
# min-slaves-max-lag 10
#
# Setting one or the other to 0 disables the feature.
#
# By default min-slaves-to-write is set to 0 (feature disabled) and
# min-slaves-max-lag is set to 10.

# A Redis master is able to list the address and port of the attached
# slaves in different ways. For example the "INFO replication" section
# offers this information, which is used, among other tools, by
# Redis Sentinel in order to discover slave instances.
# Another place where this info is available is in the output of the
# "ROLE" command of a master.
#
# The listed IP and address normally reported by a slave is obtained
# in the following way:
#
#   IP: The address is auto detected by checking the peer address
#   of the socket used by the slave to connect with the master.
#
#   Port: The port is communicated by the slave during the replication
#   handshake, and is normally the port that the slave is using to
#   list for connections.
#
# However when port forwarding or Network Address Translation (NAT) is
# used, the slave may be actually reachable via different IP and port
# pairs. The following two options can be used by a slave in order to
# report to its master a specific set of IP and port, so that both INFO
# and ROLE will report those values.
#
# There is no need to use both the options if you need to override just
# the port or the IP address.
#
# slave-announce-ip 5.5.5.5
# slave-announce-port 1234

# 安全
################################## SECURITY ###################################

# Require clients to issue AUTH <PASSWORD> before processing any other
# commands.  This might be useful in environments in which you do not trust
# others with access to the host running redis-server.
#
# This should stay commented out for backward compatibility and because most
# people do not need auth (e.g. they run their own servers).
#
# Warning: since Redis is pretty fast an outside user can try up to
# 150k passwords per second against a good box. This means that you should
# use a very strong password otherwise it will be very easy to break.
#
#  设置redis连接密码
# requirepass foobared

# Command renaming.
#
# It is possible to change the name of dangerous commands in a shared
# environment. For instance the CONFIG command may be renamed into something
# hard to guess so that it will still be available for internal-use tools
# but not available for general clients.
#
# Example:
#
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
#
# It is also possible to completely kill a command by renaming it into
# an empty string:
# 将命令重命名,为了安全考虑,可以将某些重要的、危险的命令重命名。
# 当你把某个命令重命名成空字符串的时候就等于取消了这个命令。
# rename-command CONFIG ""
#
# Please note that changing the name of commands that are logged into the
# AOF file or transmitted to slaves may cause problems.

#客户端
################################### CLIENTS ####################################


# 设置客户端最大连接数
# maxclients 10000

# 内存管理
############################## MEMORY MANAGEMENT ################################

# 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key
# 当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,
# 会把Key存放内存,Value会存放在swap区
#
# maxmemory <bytes>

# 当内存使用达到最大值的时候,redis使用的清除策略:
#
# volatile-lru -> Evict using approximated LRU among the keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key among the ones with an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.
#
# LRU means Least Recently Used
# LFU means Least Frequently Used
#
# Both LRU, LFU and volatile-ttl are implemented using approximated
# randomized algorithms.
#
# Note: with any of the above policies, Redis will return an error on write
#       operations, when there are no suitable keys for eviction.
#
#       At the date of writing these commands are: set setnx setex append
#       incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
#       sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
#       zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
#       getset mset msetnx exec sort
#
# The default is:
#
# maxmemory-policy noeviction

# LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated
# algorithms (in order to save memory), so you can tune it for speed or
# accuracy. For default Redis will check five keys and pick the one that was
# used less recently, you can change the sample size using the following
# configuration directive.
#
# The default of 5 produces good enough results. 10 Approximates very closely
# true LRU but costs more CPU. 3 is faster but not very accurate.
#
# maxmemory-samples 5

# 在删除对象时只是进行逻辑删除,然后把对象丢给后台,让后台线程去执行真正的destruct,避免由于对象体积过大而造成阻塞
############################# LAZY FREEING ####################################

# Redis has two primitives to delete keys. One is called DEL and is a blocking
# deletion of the object. It means that the server stops processing new commands
# in order to reclaim all the memory associated with an object in a synchronous
# way. If the key deleted is associated with a small object, the time needed
# in order to execute the DEL command is very small and comparable to most other
# O(1) or O(log_N) commands in Redis. However if the key is associated with an
# aggregated value containing millions of elements, the server can block for
# a long time (even seconds) in order to complete the operation.
#
# For the above reasons Redis also offers non blocking deletion primitives
# such as UNLINK (non blocking DEL) and the ASYNC option of FLUSHALL and
# FLUSHDB commands, in order to reclaim memory in background. Those commands
# are executed in constant time. Another thread will incrementally free the
# object in the background as fast as possible.
#
# DEL, UNLINK and ASYNC option of FLUSHALL and FLUSHDB are user-controlled.
# It's up to the design of the application to understand when it is a good
# idea to use one or the other. However the Redis server sometimes has to
# delete keys or flush the whole database as a side effect of other operations.
# Specifically Redis deletes objects independently of a user call in the
# following scenarios:
#
# 1) On eviction, because of the maxmemory and maxmemory policy configurations,
#    in order to make room for new data, without going over the specified
#    memory limit.
# 2) Because of expire: when a key with an associated time to live (see the
#    EXPIRE command) must be deleted from memory.
# 3) Because of a side effect of a command that stores data on a key that may
#    already exist. For example the RENAME command may delete the old key
#    content when it is replaced with another one. Similarly SUNIONSTORE
#    or SORT with STORE option may delete existing keys. The SET command
#    itself removes any old content of the specified key in order to replace
#    it with the specified string.
# 4) During replication, when a slave performs a full resynchronization with
#    its master, the content of the whole database is removed in order to
#    load the RDB file just transfered.
#
# In all the above cases the default is to delete objects in a blocking way,
# like if DEL was called. However you can configure each case specifically
# in order to instead release memory in a non-blocking way like if UNLINK
# was called, using the following configuration directives:
# slave-lazy-flush:slave接收完RDB文件后清空数据选项
# lazyfree-lazy-eviction:内存满逐出选项
# lazyfree-lazy-expire:过期key删除选项
# lazyfree-lazy-server-del:内部删除选项,比如rename oldkey newkey时,如果newkey存在需要删除newkey
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
slave-lazy-flush no

############################## APPEND ONLY MODE ###############################

#默认redis使用的是rdb方式持久化,
#这种方式在许多应用中已经足够用了。
#但是redis如果中途宕机,会导致可能有几分钟的数据丢失,
#根据save来策略进行持久化,Append Only File是另一种持久化方式,
#可以提供更好的持久化特性。
#Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件,
#每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件

appendonly no

# The name of the append only file (default: "appendonly.aof")

appendfilename "appendonly.aof"

# The fsync() call tells the Operating System to actually write data on disk
# instead of waiting for more data in the output buffer. Some OS will really flush
# data on disk, some other OS will just try to do it ASAP.
#
# Redis supports three different modes:
#
# no: don't fsync, just let the OS flush the data when it wants. Faster.
# always: fsync after every write to the append only log. Slow, Safest.
# everysec: fsync only one time every second. Compromise.
#
# The default is "everysec", as that's usually the right compromise between
# speed and data safety. It's up to you to understand if you can relax this to
# "no" that will let the operating system flush the output buffer when
# it wants, for better performances (but if you can live with the idea of
# some data loss consider the default persistence mode that's snapshotting),
# or on the contrary, use "always" that's very slow but a bit safer than
# everysec.
#
# More details please check the following article:
# http://antirez.com/post/redis-persistence-demystified.html
#
# If unsure, use "everysec".
# no表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快。
# always表示每次写入都执行fsync,以保证数据同步到磁盘。
# everysec表示每秒执行一次fsync,可能会导致丢失这1s数据
# appendfsync always
appendfsync everysec
# appendfsync no

# 在aof重写或者写入rdb文件的时候,会执行大量IO,
#此时对于everysec和always的aof模式来说,执行fsync会造成阻塞过长时间,
#no-appendfsync-on-rewrite字段设置为默认设置为no,
#如果对延迟要求很高的应用,这个字段可以设置为yes,否则还是设置为no,
#这样对持久化特性来说这是更安全的选择。
#设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,
#默认为no,建议yes。Linux的默认fsync策略是30秒。可能丢失30秒数据.

no-appendfsync-on-rewrite no

# 当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写,
#即当aof文件增长到一定大小的时候Redis能够调用bgrewriteaof对日志文件进行重写。
#当前AOF文件大小是上次日志重写得到AOF文件大小的二倍(设置为100)时,
#自动启动新的日志重写过程

auto-aof-rewrite-percentage 100
#设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写
auto-aof-rewrite-min-size 64mb

#是否redis在启动时可以加载被截断的AOF文件
aof-load-truncated yes

# Redis 4.0 新增了 RDB-AOF 混合持久化格式, 这是一个可选的功能, 
# 在开启了这个功能之后, AOF 重写产生的文件将同时包含 RDB 格式的内容和 AOF 格式的内容,
# 其中 RDB 格式的内容用于记录已有的数据, 而 AOF 格式的内存则用于记录最近发生了变化的数据,
# 这样 Redis 就可以同时兼有 RDB 持久化和 AOF 持久化的优点 —— 既能够快速地生成重写文件, 也能够在出现问题时, 快速地载入数据
aof-use-rdb-preamble no

################################ LUA SCRIPTING  ###############################

# Max execution time of a Lua script in milliseconds.
#
# If the maximum execution time is reached Redis will log that a script is
# still in execution after the maximum allowed time and will start to
# reply to queries with an error.
#
# When a long running script exceeds the maximum execution time only the
# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be
# used to stop a script that did not yet called write commands. The second
# is the only way to shut down the server in the case a write command was
# already issued by the script but the user doesn't want to wait for the natural
# termination of the script.
#
# Set it to 0 or a negative value for unlimited execution without warnings.
lua-time-limit 5000

#集群设置
################################ REDIS CLUSTER  ###############################
#
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# WARNING EXPERIMENTAL: Redis Cluster is considered to be stable code, however
# in order to mark it as "mature" we need to wait for a non trivial percentage
# of users to deploy it in production.
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#
# Normal Redis instances can't be part of a Redis Cluster; only nodes that are
# started as cluster nodes can. In order to start a Redis instance as a
# 默认是不开启集群模式
# cluster-enabled yes

# Every cluster node has a cluster configuration file. This file is not
# intended to be edited by hand. It is created and updated by Redis nodes.
# Every Redis Cluster node requires a different cluster configuration file.
# Make sure that instances running in the same system do not have
# overlapping cluster configuration file names.
# 集群配置文件的名称,每个节点都有一个集群相关的配置文件,持久化保存集群的信息
# cluster-config-file nodes-6379.conf

# Cluster node timeout is the amount of milliseconds a node must be unreachable
# for it to be considered in failure state.
# Most other internal time limits are multiple of the node timeout.
#  节点相互连接的超时时间
# cluster-node-timeout 15000

# A slave of a failing master will avoid to start a failover if its data
# looks too old.
#
# There is no simple way for a slave to actually have an exact measure of
# its "data age", so the following two checks are performed:
#
# 1) If there are multiple slaves able to failover, they exchange messages
#    in order to try to give an advantage to the slave with the best
#    replication offset (more data from the master processed).
#    Slaves will try to get their rank by offset, and apply to the start
#    of the failover a delay proportional to their rank.
#
# 2) Every single slave computes the time of the last interaction with
#    its master. This can be the last ping or command received (if the master
#    is still in the "connected" state), or the time that elapsed since the
#    disconnection with the master (if the replication link is currently down).
#    If the last interaction is too old, the slave will not try to failover
#    at all.
#
# The point "2" can be tuned by user. Specifically a slave will not perform
# the failover if, since the last interaction with the master, the time
# elapsed is greater than:
#
#   (node-timeout * slave-validity-factor) + repl-ping-slave-period
#
# So for example if node-timeout is 30 seconds, and the slave-validity-factor
# is 10, and assuming a default repl-ping-slave-period of 10 seconds, the
# slave will not try to failover if it was not able to talk with the master
# for longer than 310 seconds.
#
# A large slave-validity-factor may allow slaves with too old data to failover
# a master, while a too small value may prevent the cluster from being able to
# elect a slave at all.
#
# For maximum availability, it is possible to set the slave-validity-factor
# to a value of 0, which means, that slaves will always try to failover the
# master regardless of the last time they interacted with the master.
# (However they'll always try to apply a delay proportional to their
# offset rank).
#
# Zero is the only value able to guarantee that when all the partitions heal
# the cluster will always be able to continue.
# 用来判断slave节点与master断线的时间是否过长
# cluster-slave-validity-factor 10

# Cluster slaves are able to migrate to orphaned masters, that are masters
# that are left without working slaves. This improves the cluster ability
# to resist to failures as otherwise an orphaned master can't be failed over
# in case of failure if it has no working slaves.
#
# Slaves migrate to orphaned masters only if there are still at least a
# given number of other working slaves for their old master. This number
# is the "migration barrier". A migration barrier of 1 means that a slave
# will migrate only if there is at least 1 other working slave for its master
# and so forth. It usually reflects the number of slaves you want for every
# master in your cluster.
#
# Default is 1 (slaves migrate only if their masters remain with at least
# one slave). To disable migration just set it to a very large value.
# A value of 0 can be set but is useful only for debugging and dangerous
# in production.
#
# cluster-migration-barrier 1

# By default Redis Cluster nodes stop accepting queries if they detect there
# is at least an hash slot uncovered (no available node is serving it).
# This way if the cluster is partially down (for example a range of hash slots
# are no longer covered) all the cluster becomes, eventually, unavailable.
# It automatically returns available as soon as all the slots are covered again.
#
# However sometimes you want the subset of the cluster which is working,
# to continue to accept queries for the part of the key space that is still
# covered. In order to do so, just set the cluster-require-full-coverage
# option to no.
#
# cluster-require-full-coverage yes

# In order to setup your cluster make sure to read the documentation
# available at http://redis.io web site.

#集群Docker/NAT支持
########################## CLUSTER DOCKER/NAT support  ########################

# In certain deployments, Redis Cluster nodes address discovery fails, because
# addresses are NAT-ted or because ports are forwarded (the typical case is
# Docker and other containers).
#
# In order to make Redis Cluster working in such environments, a static
# configuration where each node knows its public address is needed. The
# following two options are used for this scope, and are:
#
# * cluster-announce-ip
# * cluster-announce-port
# * cluster-announce-bus-port
#
# Each instruct the node about its address, client port, and cluster message
# bus port. The information is then published in the header of the bus packets
# so that other nodes will be able to correctly map the address of the node
# publishing the information.
#
# If the above options are not used, the normal Redis Cluster auto-detection
# will be used instead.
#
# Note that when remapped, the bus port may not be at the fixed offset of
# clients port + 10000, so you can specify any port and bus-port depending
# on how they get remapped. If the bus-port is not set, a fixed offset of
# 10000 will be used as usually.
#
# Example:
#
# cluster-announce-ip 10.1.1.5
# cluster-announce-port 6379
# cluster-announce-bus-port 6380

# 慢日志
################################## SLOW LOG ###################################

# The Redis Slow Log is a system to log queries that exceeded a specified
# execution time. The execution time does not include the I/O operations
# like talking with the client, sending the reply and so forth,
# but just the time needed to actually execute the command (this is the only
# stage of command execution where the thread is blocked and can not serve
# other requests in the meantime).
#
# You can configure the slow log with two parameters: one tells Redis
# what is the execution time, in microseconds, to exceed in order for the
# command to get logged, and the other parameter is the length of the
# slow log. When a new command is logged the oldest one is removed from the
# queue of logged commands.

# The following time is expressed in microseconds, so 1000000 is equivalent
# to one second. Note that a negative number disables the slow log, while
# a value of zero forces the logging of every command.
# 记录查询时间大于10000微秒的查询
slowlog-log-slower-than 10000

# There is no limit to this length. Just be aware that it will consume memory.
# You can reclaim memory used by the slow log with SLOWLOG RESET.
# 保存128条日志
slowlog-max-len 128

# 延迟监控
################################ LATENCY MONITOR ##############################

# The Redis latency monitoring subsystem samples different operations
# at runtime in order to collect data related to possible sources of
# latency of a Redis instance.
#
# Via the LATENCY command this information is available to the user that can
# print graphs and obtain reports.
#
# The system only logs operations that were performed in a time equal or
# greater than the amount of milliseconds specified via the
# latency-monitor-threshold configuration directive. When its value is set
# to zero, the latency monitor is turned off.
#
# By default latency monitoring is disabled since it is mostly not needed
# if you don't have latency issues, and collecting data has a performance
# impact, that while very small, can be measured under big load. Latency
# monitoring can easily be enabled at runtime using the command
# "CONFIG SET latency-monitor-threshold <milliseconds>" if needed.
# redis延时监控系统在运行时会采样一些操作,以便收集可能导致延时的数据根源。
# 通过 LATENCY命令 可以打印一些图样和获取一些报告,方便监控
# 这个系统仅仅记录那个执行时间大于或等于预定时间(毫秒)的操作,
# 这个预定时间是通过latency-monitor-threshold配置来指定的,
# 当设置为0时,这个监控系统处于停止状态
latency-monitor-threshold 0

#事件通知
############################# EVENT NOTIFICATION ##############################

# Redis can notify Pub/Sub clients about events happening in the key space.
# This feature is documented at http://redis.io/topics/notifications
#
# For instance if keyspace events notification is enabled, and a client
# performs a DEL operation on key "foo" stored in the Database 0, two
# messages will be published via Pub/Sub:
#
# PUBLISH __keyspace@0__:foo del
# PUBLISH __keyevent@0__:del foo
#
# It is possible to select the events that Redis will notify among a set
# of classes. Every class is identified by a single character:
#
#  K     Keyspace events, published with __keyspace@<db>__ prefix.
#  E     Keyevent events, published with __keyevent@<db>__ prefix.
#  g     Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...
#  $     String commands
#  l     List commands
#  s     Set commands
#  h     Hash commands
#  z     Sorted set commands
#  x     Expired events (events generated every time a key expires)
#  e     Evicted events (events generated when a key is evicted for maxmemory)
#  A     Alias for g$lshzxe, so that the "AKE" string means all the events.
#
#  The "notify-keyspace-events" takes as argument a string that is composed
#  of zero or multiple characters. The empty string means that notifications
#  are disabled.
#
#  Example: to enable list and generic events, from the point of view of the
#           event name, use:
#
#  notify-keyspace-events Elg
#
#  Example 2: to get the stream of the expired keys subscribing to channel
#             name __keyevent@0__:expired use:
#
#  notify-keyspace-events Ex
#
#  By default all notifications are disabled because most users don't need
#  this feature and the feature has some overhead. Note that if you don't
#  specify at least one of K or E, no events will be delivered.
notify-keyspace-events ""

# 高级配置
############################### ADVANCED CONFIG ###############################

# Hashes are encoded using a memory efficient data structure when they have a
# small number of entries, and the biggest entry does not exceed a given
# threshold. These thresholds can be configured using the following directives.
# 设置hashtable中元素的总个数不超过设定数量时,就用zipmap的方式来存储hashtable以节省内存
hash-max-ziplist-entries 512
# hashtable中的key以及value的长度小于设定的值时,就用zipmap的方式来存储hashtable以节省内存
hash-max-ziplist-value 64

# Lists are also encoded in a special way to save a lot of space.
# The number of entries allowed per internal list node can be specified
# as a fixed maximum size or a maximum number of elements.
# For a fixed maximum size, use -5 through -1, meaning:
# -5: max size: 64 Kb  <-- not recommended for normal workloads
# -4: max size: 32 Kb  <-- not recommended
# -3: max size: 16 Kb  <-- probably not recommended
# -2: max size: 8 Kb   <-- good
# -1: max size: 4 Kb   <-- good
# Positive numbers mean store up to _exactly_ that number of elements
# per list node.
# The highest performing option is usually -2 (8 Kb size) or -1 (4 Kb size),
# but if your use case is unique, adjust the settings as necessary.
list-max-ziplist-size -2

# Lists may also be compressed.
# Compress depth is the number of quicklist ziplist nodes from *each* side of
# the list to *exclude* from compression.  The head and tail of the list
# are always uncompressed for fast push/pop operations.  Settings are:
# 0: disable all list compression
# 1: depth 1 means "don't start compressing until after 1 node into the list,
#    going from either the head or tail"
#    So: [head]->node->node->...->node->[tail]
#    [head], [tail] will always be uncompressed; inner nodes will compress.
# 2: [head]->[next]->node->node->...->node->[prev]->[tail]
#    2 here means: don't compress head or head->next or tail->prev or tail,
#    but compress all nodes between them.
# 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail]
# etc.
list-compress-depth 0

# Sets have a special encoding in just one case: when a set is composed
# of just strings that happen to be integers in radix 10 in the range
# of 64 bit signed integers.
# The following configuration setting sets the limit in the size of the
# set in order to use this special memory saving encoding.
set-max-intset-entries 512

# Similarly to hashes and lists, sorted sets are also specially encoded in
# order to save a lot of space. This encoding is only used when the length and
# elements of a sorted set are below the following limits:
zset-max-ziplist-entries 128
zset-max-ziplist-value 64

# HyperLogLog sparse representation bytes limit. The limit includes the
# 16 bytes header. When an HyperLogLog using the sparse representation crosses
# this limit, it is converted into the dense representation.
#
# A value greater than 16000 is totally useless, since at that point the
# dense representation is more memory efficient.
#
# The suggested value is ~ 3000 in order to have the benefits of
# the space efficient encoding without slowing down too much PFADD,
# which is O(N) with the sparse encoding. The value can be raised to
# ~ 10000 when CPU is not a concern, but space is, and the data set is
# composed of many HyperLogLogs with cardinality in the 0 - 15000 range.
hll-sparse-max-bytes 3000

# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in
# order to help rehashing the main Redis hash table (the one mapping top-level
# keys to values). The hash table implementation Redis uses (see dict.c)
# performs a lazy rehashing: the more operation you run into a hash table
# that is rehashing, the more rehashing "steps" are performed, so if the
# server is idle the rehashing is never complete and some more memory is used
# by the hash table.
#
# The default is to use this millisecond 10 times every second in order to
# actively rehash the main dictionaries, freeing memory when possible.
#
# If unsure:
# use "activerehashing no" if you have hard latency requirements and it is
# not a good thing in your environment that Redis can reply from time to time
# to queries with 2 milliseconds delay.
#
# use "activerehashing yes" if you don't have such hard requirements but
# want to free memory asap when possible.
activerehashing yes

# The client output buffer limits can be used to force disconnection of clients
# that are not reading data from the server fast enough for some reason (a
# common reason is that a Pub/Sub client can't consume messages as fast as the
# publisher can produce them).
#
# The limit can be set differently for the three different classes of clients:
#
# normal -> normal clients including MONITOR clients
# slave  -> slave clients
# pubsub -> clients subscribed to at least one pubsub channel or pattern
#
# The syntax of every client-output-buffer-limit directive is the following:
#
# client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>
#
# A client is immediately disconnected once the hard limit is reached, or if
# the soft limit is reached and remains reached for the specified number of
# seconds (continuously).
# So for instance if the hard limit is 32 megabytes and the soft limit is
# 16 megabytes / 10 seconds, the client will get disconnected immediately
# if the size of the output buffers reach 32 megabytes, but will also get
# disconnected if the client reaches 16 megabytes and continuously overcomes
# the limit for 10 seconds.
#
# By default normal clients are not limited because they don't receive data
# without asking (in a push way), but just after a request, so only
# asynchronous clients may create a scenario where data is requested faster
# than it can read.
#
# Instead there is a default limit for pubsub and slave clients, since
# subscribers and slaves receive data in a push fashion.
#
# Both the hard or the soft limit can be disabled by setting them to zero.
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60

# Redis calls an internal function to perform many background tasks, like
# closing connections of clients in timeout, purging expired keys that are
# never requested, and so forth.
#
# Not all tasks are performed with the same frequency, but Redis checks for
# tasks to perform according to the specified "hz" value.
#
# By default "hz" is set to 10. Raising the value will use more CPU when
# Redis is idle, but at the same time will make Redis more responsive when
# there are many keys expiring at the same time, and timeouts may be
# handled with more precision.
#
# The range is between 1 and 500, however a value over 100 is usually not
# a good idea. Most users should use the default of 10 and raise this up to
# 100 only in environments where very low latency is required.
# Redis server执行后台任务的频率
hz 10

# When a child rewrites the AOF file, if the following option is enabled
# the file will be fsync-ed every 32 MB of data generated. This is useful
# in order to commit the file to the disk more incrementally and avoid
# big latency spikes.
# 当一个子节点重写AOF文件时,如果启用下面的选项,则文件每生成32M数据进行同步
aof-rewrite-incremental-fsync yes

# Redis LFU eviction (see maxmemory setting) can be tuned. However it is a good
# idea to start with the default settings and only change them after investigating
# how to improve the performances and how the keys LFU change over time, which
# is possible to inspect via the OBJECT FREQ command.
#
# There are two tunable parameters in the Redis LFU implementation: the
# counter logarithm factor and the counter decay time. It is important to
# understand what the two parameters mean before changing them.
#
# The LFU counter is just 8 bits per key, it's maximum value is 255, so Redis
# uses a probabilistic increment with logarithmic behavior. Given the value
# of the old counter, when a key is accessed, the counter is incremented in
# this way:
#
# 1. A random number R between 0 and 1 is extracted.
# 2. A probability P is calculated as 1/(old_value*lfu_log_factor+1).
# 3. The counter is incremented only if R < P.
#
# The default lfu-log-factor is 10. This is a table of how the frequency
# counter changes with a different number of accesses with different
# logarithmic factors:
#
# +--------+------------+------------+------------+------------+------------+
# | factor | 100 hits   | 1000 hits  | 100K hits  | 1M hits    | 10M hits   |
# +--------+------------+------------+------------+------------+------------+
# | 0      | 104        | 255        | 255        | 255        | 255        |
# +--------+------------+------------+------------+------------+------------+
# | 1      | 18         | 49         | 255        | 255        | 255        |
# +--------+------------+------------+------------+------------+------------+
# | 10     | 10         | 18         | 142        | 255        | 255        |
# +--------+------------+------------+------------+------------+------------+
# | 100    | 8          | 11         | 49         | 143        | 255        |
# +--------+------------+------------+------------+------------+------------+
#
# NOTE: The above table was obtained by running the following commands:
#
#   redis-benchmark -n 1000000 incr foo
#   redis-cli object freq foo
#
# NOTE 2: The counter initial value is 5 in order to give new objects a chance
# to accumulate hits.
#
# The counter decay time is the time, in minutes, that must elapse in order
# for the key counter to be divided by two (or decremented if it has a value
# less <= 10).
#
# The default value for the lfu-decay-time is 1. A Special value of 0 means to
# decay the counter every time it happens to be scanned.
#
# lfu-log-factor 10
# lfu-decay-time 1

# 碎片整理
########################### ACTIVE DEFRAGMENTATION #######################
#
# WARNING THIS FEATURE IS EXPERIMENTAL. However it was stress tested
# even in production and manually tested by multiple engineers for some
# time.
#
# What is active defragmentation?
# -------------------------------
#
# Active (online) defragmentation allows a Redis server to compact the
# spaces left between small allocations and deallocations of data in memory,
# thus allowing to reclaim back memory.
#
# Fragmentation is a natural process that happens with every allocator (but
# less so with Jemalloc, fortunately) and certain workloads. Normally a server
# restart is needed in order to lower the fragmentation, or at least to flush
# away all the data and create it again. However thanks to this feature
# implemented by Oran Agra for Redis 4.0 this process can happen at runtime
# in an "hot" way, while the server is running.
#
# Basically when the fragmentation is over a certain level (see the
# configuration options below) Redis will start to create new copies of the
# values in contiguous memory regions by exploiting certain specific Jemalloc
# features (in order to understand if an allocation is causing fragmentation
# and to allocate it in a better place), and at the same time, will release the
# old copies of the data. This process, repeated incrementally for all the keys
# will cause the fragmentation to drop back to normal values.
#
# Important things to understand:
#
# 1. This feature is disabled by default, and only works if you compiled Redis
#    to use the copy of Jemalloc we ship with the source code of Redis.
#    This is the default with Linux builds.
#
# 2. You never need to enable this feature if you don't have fragmentation
#    issues.
#
# 3. Once you experience fragmentation, you can enable this feature when
#    needed with the command "CONFIG SET activedefrag yes".
#
# The configuration parameters are able to fine tune the behavior of the
# defragmentation process. If you are not sure about what they mean it is
# a good idea to leave the defaults untouched.

# Enabled active defragmentation
# activedefrag yes

# Minimum amount of fragmentation waste to start active defrag
# active-defrag-ignore-bytes 100mb

# Minimum percentage of fragmentation to start active defrag
# active-defrag-threshold-lower 10

# Maximum percentage of fragmentation at which we use maximum effort
# active-defrag-threshold-upper 100

# Minimal effort for defrag in CPU percentage
# active-defrag-cycle-min 25

# Maximal effort for defrag in CPU percentage
# active-defrag-cycle-max 75

Redis持久化

RDB(Redis DataBase)

是什么?
  • 在指定的时间间隔内将内存中的数据集体快照写入磁盘

  • 行话是Snapshot快照,它恢复时是将快照文件直接读到内存里

  • 写入磁盘原理

    Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了(时间间隔内的新的改动全保存完了),再用这个临时文件替换上次持久化好的文件。

    整个过程中,主进程不进行任何IO操作,这就确保了极高的性能。

    Fork

    Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。

  • RDB保存的是dump.rdb文件,文件名可在通过 dbfilename dump.rdb 配置

触发RDB快照
  • 执行命令save或者bgsave

    • save:save时只管保存,其它不管,全部阻塞
    • bgsave:Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。可以通过lastsave命令获取最后一次成功执行快照的时间
  • 执行flushall命令,也会产生dump.rdb文件,但是里面是空的,无意义

  • redis.conf 的 save {seconds} {changes} 配置 保存数据到磁盘

    • save 900 1

      15分钟有一个key发生变化就保存数据到磁盘

    • save 300 10

      5分钟有10个key发生变化就保存数据到磁盘

    • save 60 10000

      1分钟有10000个key发生变化就保存数据到磁盘

如何恢复
  • 将备份文件(dump.rdb)移动到redis安装目录并启动服务即可
  • CONFIG GET dir 获取目录
优势与劣势

优势

  • 适合大规模的数据恢复
  • 对数据完整性和一致性要求不高

劣势

  • 在一定时间间隔做一次备份,如果redis意外挂掉的话,就会丢失最后一次快照后的所有修改
  • Fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑
  • 当数据集比较大的时候,fork的过程会非常的耗时,可能会导致Redis在一些毫秒级不能回应客户端请求
如何停止

动态停止所有RDB保存规则的方法:redis-cli config set save “”

AOF(Append Only File)

定义
  • 以日志的形式来记录每个写操作,将Redis执行过的所有指令记录下来(读操作不记录)

  • 只允许追加文件不可以改写文件,redis启动之初会读取该文件重新构建数据(redis重启的话就根据日志文件的内容将写指令从前执行到后执行一次完成数据的恢复工作)

  • 保存日志的文件名是 appendoly.aop 可通过 appendfilename 参数修改文件名

AOF 启动/修复/恢复

正常恢复

  • 启动:设置Yes 修改默认的 appendonly no 改为yes
  • 将有数据的aof文件复制一份保存到对应目录(config get dir)
  • 恢复:重启redis然后重新加载

异常恢复

  • appendonly yes
  • 备份被写坏的AOF文件
  • 修复:redis-check-aof --fix 进行修复
  • 恢复:重启redis然后重新加载
rewrite

定义:AOF采用文件追加方式,文件会越来越大。为避免出现此种情况,新增了重写机制,当AOF文件大小超过所设定的阈值时,Redis就会启动AOF文件的压缩内容,只保留可以恢复数据的最小指令集。

重写原理:AOF文件持续增长而过大时,会fork除一条新进程来将文件重写,遍历新进程的内存中数据,每条记录有一条的Set语句。

重写AOF文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的AOF文件。

触发机制:Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发

优势与劣势

优势:

  • 每次修改同步:appendfsync always 同步持久化 每次发生数据变更会被立即记录到磁盘,性能较差但数据完整性比较好
  • 每秒同步:appendfsync everysec 异步操作,每秒记录,如果一秒内宕机,有数据丢失
  • 不同步:appendfsync no 从不同步

劣势

  • 相同数据集的数据而言AOF文件要远大于rdb文件,恢复速度慢于rdb
  • aof运行效率要慢于rdb,每秒同步策略效率较好,不同步效率和rdb相同
  • 文件操作命令易懂,文件容易被分析

Redis事务

定义:可以一次性执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞。

特性

  • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其它客户端发送来的命令请求所打断
  • 事务是一个原子操作:事务中的命令要么全部执行,要么全部都不执行
  • exec命令负责触发并执行事务中的所有命令:
    • 如果在exec执行前就已经出现报错或者断线情况,此时事务中的所有命令都不会被执行
    • 如果命令已经加入执行队列当中,执行错误只会影响单个命令的结果,后序的命令依旧可以正常执行

主要命令

multi

标记一个事务块的开始

discard

取消事务,放弃执行事务块内的所有命令。

exec

执行所有事务块内的命令

当exec被调用时,不管事务是否成功执行,对所有键的监视都会被取消,即watch命令只要在exec执行后就无效了。

watch

使得exec命令需要有条件地执行:事务只能在所有被监视键都没有被修改的前提下执行,如果这个前提条件不能满足的话,事务就不会被执行。

unwatch

取消watch命令对所有key的监视。

使用实例:

20210413121302

20210413121342

20210413121358

20210413121408

Redis 主从复制(Master主 / Slave从)

定义

主机数据库更新后根据配置和策略,自动同步到备用机上的机制。

Master以写为主,Slave以读为主。

主要作用

  1. 读写分离
  2. 容灾备份

使用流程

准备工作 - 配置
  1. 配从库不配主库

  2. 从库配置命令:slaveof 主库IP 主库端口

    每次与master断开之后,都需要重新连接,除非配置进redis.conf文件(REPLICATION)

    info replication:查看当前库信息的命令

  3. 修改配置文件的细节操作

    1. 拷贝多个redis.conf文件
    2. 开启daemonize yes
    3. pid 文件名称
    4. 指定端口
    5. log 文件名字
    6. dump.rdb名字
三种常用模式

一主二仆:一个Master两个Slave,两个Slave之间没什么关系

20210413151802

薪火相传:上一个Slave可以是下一个slave的Master,Slave同样可以接收其他slave的连接和同步请求,那么该slave作为了链条中的下一个 master,可以有效减轻master的写压力。

中间变更转向:会清除之前的数据,重新建立拷贝最新的;原来的master shutdown之后,可以另立一台salve为主机

哨兵模式:能够后台监控主机是否故障,如果故障了根据投票自动将从库转换为主库

怎么玩:

  1. 调整结构,6379带着6380、6381
  2. 新建sentinel.conf文件,名字决不能错
  3. 配置哨兵,填写内容
    1. sentinel monitor 被监控数据库名字(自己起名字)127.0.0.1 6379 1
    2. 上面最后一个数字1,表示主机挂掉后slave投票看让谁接替成为主机,得票数多少后成为主机
  4. 启动哨兵 redis-sentinel /sentinel.conf
  5. 正常主从演示
  6. 原有的master挂了
  7. 投票新选
  8. 重新主从继续开工,info replication查查看

问题:如果之前挂了的master重启回来,会不会双master冲突? 不会,原master,变成slave

复制原理

  1. slave启动成功连接到master后会发送一个sync命令
  2. master接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,以完成一次完全同步
  3. 全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中
  4. 增量复制:Master继续将新的所有收集到的修改命令依旧传给slave,完成同步
  5. 但是只要是重新连接master,一次完全同步(全量复制)将被自动执行

主从复制的缺点

复制延时:由于所有的写操作都是先在master上操作,然后同步更新到slave上,所以从master同步到slave机器有一定的延迟,当系统很繁忙的时候,延迟问题更加严重,Slave机器数量的增加也会使这个问题更加严重。

主从问题演示

  • 切入点问题,slave1、slave2是从头开始复制还是从切入点开始复制?比如从k4进来,那之前的k1、k2、k3是否也可以复制?

    从头开始复制;123也可以复制

  • 从机是否可以写?set可否?

    从机不可以写,不可set

  • 主机shutdown后情况如何?从机是上位还是原地待命

    从机还是原地待命(一主二从模式,其它模式可以另立主机)

  • 主机又回来了之后,主机新增记录,从机还能否顺利复制?

  • 其中一台从机down后情况如何?依照原有它能跟上大部队吗?

    不能跟上,每次与master断开之后,都需要从新连接,除非你配置进redis.conf文件

Redis 类

主要类:Jedis、JedisPool、JedisPoolConfig

JedisPool配置参数:

  • maxActive:控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted。

  • maxIdle:控制一个pool最多有多少个状态为idle(空闲)的jedis实例;

  • whenExhaustedAction

    表示当pool中的jedis实例都被allocated完时,pool要采取的操作;默认有三种。

    • WHEN_EXHAUSTED_FAIL --> 表示无jedis实例时,直接抛出NoSuchElementException;
    • WHEN_EXHAUSTED_BLOCK --> 则表示阻塞住,或者达到maxWait时抛出JedisConnectionException;
    • WHEN_EXHAUSTED_GROW --> 则表示新建一个jedis实例,也就说设置的maxActive无用;
  • maxWait:表示当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛JedisConnectionException;

  • testOnBorrow:获得一个jedis实例的时候是否检查连接可用性(ping());如果为true,则得到的jedis实例均是可用的;

  • testOnReturn:return 一个jedis实例给pool时,是否检查连接可用性(ping());

  • testWhileIdle:如果为true,表示有一个idle object evitor线程对idle object进行扫描,如果validate失败,此object会被从pool中drop掉;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义;

  • timeBetweenEvictionRunsMillis:表示idle object evitor两次扫描之间要sleep的毫秒数;

  • numTestsPerEvictionRun:表示idle object evitor每次扫描的最多的对象数;

  • minEvictableIdleTimeMillis:表示一个对象至少停留在idle状态的最短时间,然后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义;

  • softMinEvictableIdleTimeMillis:在minEvictableIdleTimeMillis基础上,加入了至少minIdle个对象已经在pool里面了。如果为-1,evicted不会根据idle time驱逐任何对象。如果minEvictableIdleTimeMillis>0,则此项设置无意义,且只有在timeBetweenEvictionRunsMillis大于0时才有意义;

  • lifo:borrowObject返回对象时,是采用DEFAULT_LIFO(last in first out,即类似cache的最频繁使用队列),如果为False,则表示FIFO队列;

参考素材

https://my.oschina.net/jallenkwong/blog/4411044
https://www.bilibili.com/video/BV1oW411u75R

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值