redis

安装

docker run --name wltjzbjg_redis -p 7001:6379 -v /root/docker/redis/data:/data -v /root/docker/redis/conf/redis.conf:/etc/redis/redis.conf -d redis redis-server /etc/redis/redis.conf

docker run --name lmqredis -p 6379:6379 -v /root/docker/redis/data:/data -v /root/docker/redis/conf/redis.conf:/etc/redis/redis.conf -d redis redis-server /etc/redis/redis.conf

docker run --name lmqredis -p 6379:6379 -v /mydata/redis/test/data:/data -v /mydata/redis/test/conf:/etc/redis -di redis redis-server /etc/redis/redis.conf

docker run --name MYSQL -e MYSQL_ROOT_PASSWORD=123456 -p 3309:3306 -itd mysql:5.7 /bin/bash

修改密码

如 将redis密码设置成1234567
命令:config set requirepass 1234567

性能测试

语法

redis 性能测试的基本命令如下:

redis-benchmark [option] [option value]

案例

redis-benchmark -n 10000  -q

PING_INLINE: 141043.72 requests per second
PING_BULK: 142857.14 requests per second
SET: 141442.72 requests per second
GET: 145348.83 requests per second
INCR: 137362.64 requests per second
LPUSH: 145348.83 requests per second
LPOP: 146198.83 requests per second
SADD: 146198.83 requests per second
SPOP: 149253.73 requests per second
LPUSH (needed to benchmark LRANGE): 148588.42 requests per second
LRANGE_100 (first 100 elements): 58411.21 requests per second
LRANGE_300 (first 300 elements): 21195.42 requests per second
LRANGE_500 (first 450 elements): 14539.11 requests per second
LRANGE_600 (first 600 elements): 10504.20 requests per second
MSET (10 keys): 93283.58 requests per second

参数

redis 性能测试工具可选参数如下所示:

序号 选项 描述 默认值
1 -h 指定服务器主机名 127.0.0.1
2 -p 指定服务器端口 6379
3 -s 指定服务器 socket
4 -c 指定并发连接数 50
5 -n 指定请求数 10000
6 -d 以字节的形式指定 SET/GET 值的数据大小 2
7 -k 1=keep alive 0=reconnect 1
8 -r SET/GET/INCR 使用随机 key, SADD 使用随机值
9 -P 通过管道传输 请求 1
10 -q 强制退出 redis。仅显示 query/sec 值
11 --csv 以 CSV 格式输出
12 *-l*(L 的小写字母) 生成循环,永久执行测试
13 -t 仅运行以逗号分隔的测试命令列表。
14 *-I*(i 的大写字母) Idle 模式。仅打开 N 个 idle 连接并等待。

性能测试

redis-benchmark -h 127.0.0.1 -p 6379 -t set,lpush -n 10000 -q

SET: 146198.83 requests per second
LPUSH: 145560.41 requests per second

基础知识

redis 默认有16个数据库

默认使用的第0个

可以使用select进行切换数据库

select 3   # 切换数据库

dbsize     # 查看db大小


keys *     #查看数据库所有的key

清除当前数据库flushdb

清除全部数据库内容flushall

为什么Redis是6379(了解)

Alessia Merz 是一位意大利舞女、女演员。 Redis 作者 Antirez 早年看电视节目,觉得 Merz 在节目中的一些话愚蠢可笑,Antirez 喜欢造“梗”用于平时和朋友们交流,于是造了一个词 "MERZ",形容愚蠢,与 "stupid" 含义相同。

redis 是单线程的!

明白redis是很快的,官方表示Redis 是基于内存操作,CPU不是Redis性能瓶颈,Redis的瓶颈是根据机器的内存和网络带宽,既然可以实现单线程来实现,就使用单线程了!所有就使用了单线程了!

Redis 是C语言写的,官方提供的数据100000+的QPS,完全不比同样是使用key-vale的Memecache差!

Redis为什么单线程还这么快?

1、 误区1:高性能的服务器一定是多线程?

2、 误区2:多线程(CPU上下文会切换!)一定比单线程效率高!

先去CPU > 内存 > 硬盘的速度 要有所了解

核心:redis是将所有的数据全部放在内存中的,所以说使用单线程去操作效率就是最高的,多线程(CPU上下文会切换,耗时操作!!!),对于内存系统莱索,如果没有上下文切换效率最高!多次读写都是在一个CPU上的

五大数据类型

官网文档

image-20230809161312227

所有的命令要全部记住 jedis

单点登录

Redis-key

keys *

EXists key 	# 判断当前key是否存在

move key 1  	# 移除当前的key

expire key 10  	# 设置过期时间  时间单位秒

ttl key  		# 查看过期时间


type key        # 查看数据类型

遇到不会的可以在官网查看 redis命令手册

String(字符串)

90%的java程序员使用redis只会使用一个String类型

flushall  # 清除所有

append key1 hello  # 在后面添加  返回字符串长度   不存在就相当于set key 

strlen key   # 查看字符串长度

getrange key 0 3 # 获取字符串部分

getrange key 0 -1 # 获取全部字符串 和 getkey一样

setrange key2 1 xxx   # 字符串替换   指定开始的位置

incr key  # 相当于i++

decr key  # 相当于i--

# 步长

incrby views 10 # 加10

decrby views 10 # 减10



setex (set with expire)  #  
setex key3 30 "hello"  # 设置30 秒后过期

setnx  (set if not exits)# 不存在设置 存在就不保存
setnx lmq "redis" # 如果不存在就创建lmq 否则就创建失败


# 批量设置值
mset k1 v1 k2 v2 k3 v3
mget k1 k2 k3
msetnx k1 v1 k2 v2 k3 v3  # 原子操作  要么一起成功 要么一起失败
mget k1 k2 k3


set user:1 {name:zhangsan,age:3}   # 设置一个user:1 对象 值为{name:zhangsan,age:3} 



mset user:2:name zs user:2:age 2
mget user:2:name user:2:age


getset # 存在就显示值然后重新设置


数据结构是相关的

String 类似的场景 value除了是我们的字符串还可以是我们的数字!

  • 计数器
  • 统计多单位的数量 如 : uid:123:follow
  • 粉丝数
  • 对象缓存存储

List(列表)

基本的数据类型,列表

在Redis里面 我们可以把list玩成 栈 队列 阻塞队列!

所有的list命令都是用l开头的

可以想象为一个队列 默认左边操作

lpush list one   # 一个值或者多个值插入[在前面插入] 创建列表[lpush]  名字[list]  数据[one]


rpush list righr  # 在后面添加
 
lpop list   # 左边移除

rpop list   # 右边移除


lrange list 0 -1  # 读取列表[lrange]  名字[list] 范围[0 -1]   

lrange list 0 1  # 读取列表[lrange]  名字[list] 范围[0 1]   倒着输出

lindex list 1   # 按下标取出

llen  list # 返回列表长度

lrem list 1 one  # 移除指定的值   个数  元素

ltrim list 1 2 # 通过下标截取指定长度, 这个list已经改变了 截断了只剩下的元素   从0开始计算


rpoplpush source destination
rpoplpush  mylist newmylist # 移除列表最后一个元素,添加到另一个新列表里面


exists list # 查看数组是否存在

lset list 0 lmq  #  更新操作  要求下标存在

linset list before "word" "other"


linset list before "hello1" "lmq" # 在hello1 前面添加lmq

linset list after "hello1" "lmq" # 在hello1 后面添加lmq


小结

  • 他实际上是一个链表 , before、Node、after\left\right 都可以插入
  • 如果key不存在,创建新的链表
  • 如果key存在,新增内容
  • 如果移除了所有值,空链表也代表不存在
  • 在两边插入或者改动,效率最高!中间元素,相对来说效率会底一点

消息排队!消息队列(Lpush Rpop) 栈(Lpush Lpop)!

Set(集合)

set 中的值不能重复读!

set 无序不重复的集合。随机抽取


sadd mytest "hello"  # set 集合中添加

SMEMBERS mytest  # 查看指定set的所有值

scard mytest # 获取元素个数

rem mytest hello # 删掉hello

SRANDMEMBER mytest  # 随机获得一个元素  后面可以加入个数

SRANDMEMBER mytest 2 # 随机获得2个   

spop mytest # 随机删除一个元素  后面可以加入 个数

smove mytest lmqset lmq   # 移动到一个指定另一个集合 smove 集合1 集合2  元素lmq


共同关注 (并集)

数字集合类:

  • 差集

    sdiff key1 key2
    
  • 交集

    sinter key1 key2
    
  • 并集

    sunion key1 key2
    

微博,用户将所有关注的人放在一个set集合中! 将他的粉丝也放在一个集合中!

共同关注,共同爱好 二度好友 推荐 (六度分隔理论)

Hash(哈希)

map集合 key-map!时候这个值就是map集合! 本质和String类型没有太大区别 还有一个简单的key-value!

hset myhash filed1 "123"  # 添加一个元素 到 myhash filed1   key-value
 
hget myhash filed1   # 取出 myhash filed1 的元素
 
hmset myhash field1 hello filed2 word # 插入多个
 
hmget myhash field1 filed2 # 取出多个
  
hgetall myhash # 获取全部元素

hdel myhash field1 # 删除hash指定key字段! 对应的value值

hlen myhash    # 获取字段数量

HEXISTS myhash field1 # 判断hash中指定字段是否存在

hkeys myhash # 只获得所有的key

hvals myhash  # 只获得所有value

hset myhash field1 5 # 指定增量

hincrby myhash field1 1  

hincrby myhash field1 -1

hsetnx myhash field1 hello # 判断是否存在 不存在就创建




hash 变更的数数据 user -》 name age 尤其是用户信息之类的,经常变动的信息!hash更适合于对象的存储,String更加适合字符串存储!

Zset(有序集合)

在set的基础上,增加了一个值,set

 zadd myset 1 one  # 添加元素
 
 zadd myset 2 tow 3 three  # 添加多个元素
 
  ZRANGE myset 0 -1 # 查看元素
  
  # 排序如何实现
 
zadd salary 2500 xiaoming 5000 hello2 500 123

zrangebyscore salary -inf +inf   # 显示全部用户从小到大排列

zrangebyscore salary -inf +inf withscores  # 显示全部用户从小到大排列 附带key值 成绩   -inf 负无穷 +inf  正无穷

zrange salary 0 -1 # 查看全部元素 
 
 # 移除元素 rem
 zrem salary lmq  # 移除名字为lmq元素
 
 zcard salary 3    #  获取有序
 
 zcount salary 1 3         # 获取指定区间的成员数量
 
 

其与的一些API,通过我们的学习吗? 你们剩下的如果工作中有需要,这时候你可以去查查官方文档!

案例思路:set 排序 存储[班级成绩,工资表排序]

普通消息,1,重要消息 2. 带权重进行判断!

排行榜应用消息

三种特殊数据类型

geospatial (地理位置)

朋友的定位,附近的人,打车距离计算

redis的Geo 在Redis3.2 推出的

可以查询一些测试数据

只有六个命令

image-20230809161649584

image-20230809161439604

geoadd

image-20230809163645068

# geoadd 添加地理位置 
# 规则:两级无法直接添加,我们一般会下载城市数据,直接通过java程序一次性导入!
# 参数 key 值(经度、纬度、名称)

geoadd china:city 39.90 116.40 beijin
geoadd china:city 39.90 116.40 beijin
geoadd china:city 39.90 116.40 beijin
geoadd china:city 39.90 116.40 beijin

geopos

# 获取指定城市的经度和维度
geopos china:city beijin

geodist

两个人之间的距离

单位可以使用

  • m
  • km
  • mi
  • ft
# 计算武汉到广州的直线距离

geodist china:city wuhan guangzhou km

附近的人 (获得附近所有的人的地理位置,定位!) 通过半径查询

georadius 以给定的经纬度为中心 找出某一班级的元素

我 附近的人? 前提必须纯在数据中

#  以110  30 为圆心 寻找 1000 km 为半径   前提所有的数据录入china:city

georadius china:city 110 30 1000 km

georadius china:city 110 30 1000 km withdi # 显示城市的经度和维度

georadius china:city 110 30 1000 km withcoord # 显示他人定位信息

# 获得指定数量的人, 10000人  一般显示100到200人

# 获取附近人的位置 只显示1个数据
georadius china:city 110 30 1000 km withcoord withdist count 2

GEORADIUSBYMEMBER

# 找出指定位置元素周围的其他元素!  使用同上  把输入的经纬度 换 成已经录入的城市的名字
GEORADIUSBYMEMBER china:city wuhan 1000 km

geohash 返回一个 或者多个位置元素的 Geohash表示

返回一个11 个字符串的geohash 字符串

#  将二维的经纬度转换为一维的字符串 如果两个字符串越接近南无距离就越近
geohash china:city  wuhan guangzhou

查看所有的位置

zrange china:city 0 -1 # 查看全部元素

zrem china:city beijing  # 删除一个元素

hyperloglog

什么是基数?

$$
A { 1,3,5,7,9,7 }
B { 1,3,5,7,8 }

奇数就是不重复的元素 可以接受误差
1 3 4 7 8 9
$$

简介

Redis 2,8,9 版本就更新了 Hyperloglog数据结构!

redis hyperloglog 基数统计法

优点 占用内存是固定的 2^64 不同的元素计数,只需要用 12 kb 内存 ! 如果从内存角度来看 hyperloglog 首选!

网页 UV(一个人访问一个网站多次 还是算作一个)

传统方式 set保存用户id ,然后就可以统计set中元素数量作为标准判断!

这个方式如果保存大量用户id ,就会比较麻烦 ! 我们的目的是为了计数,。而不是保存用户ID

0.81% 错误率 统计UV任务可以忽略不计


pfadd mykey a b c d e f g h i j  # 添加元素
pfcount mykey                    # 计数
pfmerge mykey3 mykey2 mykey      # 把 mykey2 和 mykey 合并到 mykey3  并集

如果允许容错 那就一定可以使用hyoerloglog

如果不允许容错 就使用set 或者自己的数据类型

bitmaps(位存储)

位存储

统计 疫情 感染人数 感染为1 未感染位0: 0 0 0 0 表示只有0和1

用户活跃和不活跃

登录和未登录

只有两个状态的都可以使用

位图 数据结构 都是操作二进制来进行记录 只有0 和 1 两个状态

记录一个星期的打卡

127.0.0.1:6379> setbit sign 0 1
(integer) 0
127.0.0.1:6379> setbit sign 1 1
(integer) 0
127.0.0.1:6379> setbit sign 2 1
(integer) 0
127.0.0.1:6379> setbit sign 3 1
(integer) 0
127.0.0.1:6379> setbit sign 4 1
(integer) 0
127.0.0.1:6379> setbit sign 5 1
(integer) 0
127.0.0.1:6379> setbit sign 6 0
(integer) 0
127.0.0.1:6379> setbit sign 7 0
(integer) 0

查看某一天是否打卡

getbit sign 5

统计操作 bitcount sign

127.0.0.1:6379> bitcount sign
(integer) 6

事务

MYSQA:ACID 同时成功 或者同时失败

事务本质 一组命令的集合 一个事务中所有的命令都会被序列化 在事务执行过程中,会按照顺序执行!

一次性 顺序性 排他性 !执行一些命令

redis事务没有隔离级别的概念

所有的命令在事务中并没有被直接执行!只有发起执行命令的时候才执行 ! exec

Redis 单条命令是保证原子性的 但是事务不保证原子性

redis的事务:

  • 开启事务 (multi)

  • 命令入队(…)

  • 执行事务(exec)

    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379(TX)> set k1 v1
    QUEUED
    127.0.0.1:6379(TX)> set k2 v3
    QUEUED
    127.0.0.1:6379(TX)> set k2 v2
    QUEUED
    127.0.0.1:6379(TX)> get k2
    QUEUED
    127.0.0.1:6379(TX)> set k3 v5
    QUEUED
    127.0.0.1:6379(TX)> exec
    
    
  • 取消事务(descard)

  • 事务有错误怎么办

编译错误

(error) EXECABORT Transaction discarded because of previous errors

事务中间不能有错误

事务中有错误所有代码都不会运行

运行错误 1/0

其他命令是可以执行的 有的错了依然可以执行

127.0.0.1:6379> set k1 "v1"
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379(TX)> INCR k1    # 执行的时候失败
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> get k3
QUEUED
127.0.0.1:6379(TX)> exec
1) (error) ERR value is not an integer or out of range
2) OK
3) OK
4) "v3"

所以redis没有原子性

监控

悲观锁:

  • 很悲观,什么时候的会出问题,无论什么都加锁

乐观锁:

  • 很乐观,认为什么时候都不会出问题, 所以不会上锁 ! 更新数据的时候去判断一下,在此之间是否有人修改过这个数据
  • 获取version
  • 更新的时候比较version

watch key 去监听元素 相当于加锁

unwatch 解锁 相当于解锁

jedis

官方推荐的java链接开发工具! 使用java操作Redis中间件 南无要对jedis 十分熟悉!

知其然知其所以然

创建链接

package com.lmq;

import redis.clients.jedis.Jedis;

/**
 * @author 羡鱼
 * @version 1.0
 * @date 2023/8/10 8:56
 */
public class TestPing {
    public static void main(String[] args) {
        // 1 new jedis 对象
        Jedis jedis = new Jedis("124.71.168.125", 6379);
        // jedis 就是原生的所有命令   指令学习很重要
        jedis.auth("123456");
        System.out.println(jedis.ping());
//        jedis.set()
    }
}

事务

package com.lmq;

import com.alibaba.fastjson.JSONObject;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

/**
 * @author 羡鱼
 * @version 1.0
 * @date 2023/8/10 9:14
 */
public class JredisSw {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("124.71.168.125", 6379);
        jedis.auth("123456");

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("hello","word");
        jsonObject.put("name","xks");

        Transaction multi = jedis.multi();
        String result = jsonObject.toString();


        try {
            multi.set("user1",result);
            multi.set("user2",result);
            multi.exec();
        } catch (Exception e) {
            multi.discard();
            throw new RuntimeException(e);
        } finally {
            System.out.println(jedis.get("user1"));
            System.out.println(jedis.get("user2"));
            jedis.close();
        }


    }
}

整合SpringBoot

springBoot 操作数据 spring-data jpa jdbc mogodb redis

springData 和 springboot 齐名

在springboot2.x之后 redis被替换为 lettuce

jedis: 采用直连 , 多个线程链接的话是不安全的,如果想要避免不安全,使用jedis pool 连接池 ! BIO 模式

lettuce:采用netty 实例可以在多个线程中进行共享,不存在线程不安全的情况 ! 可以减少线程数据,NIO 模式

整合测试

1、 导入依赖

2、 配置链接

spring:
  redis:
    port: 6379
    host: 124.71.168.125
    password: 123456

3、 测试

package com.lmq;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lmq.pojo.User;
import com.lmq.utils.RedisUtil;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class Redis02SpringbootApplicationTests {

	@Autowired
	private RedisTemplate<String,Object> redisTemplate;  //加上泛型


	@Autowired
	private RedisUtil redisUtil;

	@Test
	void contextLoads() {
//		// redisTemplate 操作不同数据类型 qpi和我们的指令是一样的
//		// opsForValue 操作字符串
//		// opsForList  操作列表
//		// opsForZSet  操作有序雷彪
//
//		redisTemplate.opsForZSet();
//
//		// 除了基本操作  connection,我们常用的方法可以直接·出来  比如事务 和基本的CRUD
//
//		// 获取redis的链接对象
//		RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
//		connection.flushDb();
//		connection.flushAll();
		redisTemplate.opsForValue().set("name","lmq");
		System.out.println(redisTemplate.opsForValue().get("name"));
		redisTemplate.opsForValue().set("文档","文档");
		System.out.println(redisTemplate.opsForValue().get("文档"));

	}

	@Test
	public void test() throws JsonProcessingException {
		User user = new User("lmq", 21);
		String jsonUser = new ObjectMapper().writeValueAsString(user);
		redisTemplate.opsForValue().set("user",jsonUser);
		System.out.println(redisTemplate.opsForValue().get("user"));

	}
	@Test
	public void test2()  {
		User user = new User("lmq", 21);
//		String jsonUser = new ObjectMapper().writeValueAsString(user);
		redisTemplate.opsForValue().set("user2",user);
		System.out.println(redisTemplate.opsForValue().get("user2"));

	}

	@Test
	public void test3(){
		redisUtil.set("lmq","hello");
		System.out.println(redisUtil.get("lmq"));
	}
}

直接传对象会报错 没有序列化

 Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.lmq.pojo.User]

自己的序列化模版

package com.lmq.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.StringRedisSerializer;

/**
 * @author 羡鱼
 * @version 1.0
 * @date 2023/8/10 11:04
 */

@Configuration
public class RedisConfig {

    // 固定模版   自己的序列化模版

    /**
     *
     * @param factory
     * @return
     */
    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory) {
        // 为了自己开发方便,一般直接使用String,Object 类型
        RedisTemplate<String,Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        // 序列化配置
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // String 的序列化转换
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash 的key 也可以采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value 序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash 的value序列化采用jackson 方式
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        return template
    }
}

实际开发不会使用原生的

package com.lmq.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 *
 */
@Component
public final class RedisUtil {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // =============================common============================
    /**
     * 指定缓存失效时间
     * @param key  键
     * @param time 时间(秒)
     */
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据key 获取过期时间
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }


    /**
     * 判断key是否存在
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 删除缓存
     * @param key 可以传一个值 或多个
     */
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
            }
        }
    }


    // ============================String=============================

    /**
     * 普通缓存获取
     * @param key 键
     * @return 值
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通缓存放入
     * @param key   键
     * @param value 值
     * @return true成功 false失败
     */

    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 普通缓存放入并设置时间
     * @param key   键
     * @param value 值
     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */

    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 递增
     * @param key   键
     * @param delta 要增加几(大于0)
     */
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }


    /**
     * 递减
     * @param key   键
     * @param delta 要减少几(小于0)
     */
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递减因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }


    // ================================Map=================================

    /**
     * HashGet
     * @param key  键 不能为null
     * @param item 项 不能为null
     */
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }

    /**
     * 获取hashKey对应的所有键值
     * @param key 键
     * @return 对应的多个键值
     */
    public Map<Object, Object> hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * HashSet
     * @param key 键
     * @param map 对应多个键值
     */
    public boolean hmset(String key, Map<String, Object> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * HashSet 并设置时间
     * @param key  键
     * @param map  对应多个键值
     * @param time 时间(秒)
     * @return true成功 false失败
     */
    public boolean hmset(String key, Map<String, Object> map, long time) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @return true 成功 false失败
     */
    public boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     *
     * @param key   键
     * @param item  项
     * @param value 值
     * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
     * @return true 成功 false失败
     */
    public boolean hset(String key, String item, Object value, long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 删除hash表中的值
     *
     * @param key  键 不能为null
     * @param item 项 可以使多个 不能为null
     */
    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }


    /**
     * 判断hash表中是否有该项的值
     *
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }


    /**
     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
     *
     * @param key  键
     * @param item 项
     * @param by   要增加几(大于0)
     */
    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }


    /**
     * hash递减
     *
     * @param key  键
     * @param item 项
     * @param by   要减少记(小于0)
     */
    public double hdecr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }


    // ============================set=============================

    /**
     * 根据key获取Set中的所有值
     * @param key 键
     */
    public Set<Object> sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 根据value从一个set中查询,是否存在
     *
     * @param key   键
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 将数据放入set缓存
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    /**
     * 将set数据放入缓存
     *
     * @param key    键
     * @param time   时间(秒)
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0)
                expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    /**
     * 获取set缓存的长度
     *
     * @param key 键
     */
    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    /**
     * 移除值为value的
     *
     * @param key    键
     * @param values 值 可以是多个
     * @return 移除的个数
     */

    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    // ===============================list=================================

    /**
     * 获取list缓存的内容
     *
     * @param key   键
     * @param start 开始
     * @param end   结束 0 到 -1代表所有值
     */
    public List<Object> lGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 获取list缓存的长度
     *
     * @param key 键
     */
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    /**
     * 通过索引 获取list中的值
     *
     * @param key   键
     * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
     */
    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 将list放入缓存
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }


    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }


    /**
     * 将list放入缓存
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒)
     * @return
     */
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 根据索引修改list中的某条数据
     *
     * @param key   键
     * @param index 索引
     * @param value 值
     * @return
     */

    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 移除N个值为value
     *
     * @param key   键
     * @param count 移除多少个
     * @param value 值
     * @return 移除的个数
     */

    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }

    }

}

redus.conf详解

启动的时候,就是通过配置文件启动的

# Redis configuration file example.
#
# Note that in order to read the configuration file, Redis must be
# started with the file path as first argument:
#
# ./redis-server /path/to/redis.conf

# Note on units: when memory size is needed, it is possible to specify
# it in the usual form of 1k 5GB 4M and so forth:
#
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
#
# units are case insensitive so 1GB 1Gb 1gB are all the same.

################################## INCLUDES ###################################

# Include one or more other config files here.  This is useful if you
# have a standard template that goes to all Redis servers but also need
# to customize a few per-server settings.  Include files can include
# other files, so use this wisely.
#
# Notice option "include" won't be rewritten by command "CONFIG REWRITE"
# from admin or Redis Sentinel. Since Redis always uses the last processed
# line as value of a configuration directive, you'd better put includes
# at the beginning of this file to avoid overwriting config change at runtime.
#
# If instead you are interested in using includes to override configuration
# options, it is better to use include as the last line.
#
# include /path/to/local.conf
# include /path/to/other.conf

################################## NETWORK #####################################

# By default, if no "bind" configuration directive is specified, Redis listens
# for connections from all the network interfaces available on the server.
# It is possible to listen to just one or multiple selected interfaces using
# the "bind" configuration directive, followed by one or more IP addresses.
#
# Examples:
#
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1 ::1
#
# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the
# internet, binding to all the interfaces is dangerous and will expose the
# instance to everybody on the internet. So by default we uncomment the
# following bind directive, that will force Redis to listen only into
# the IPv4 lookback interface address (this means Redis will be able to
# accept connections only from clients running into the same computer it
# is running).
#
# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES
# JUST COMMENT THE FOLLOWING LINE.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bind 127.0.0.1

# Protected mode is a layer of security protection, in order to avoid that
# Redis instances left open on the internet are accessed and exploited.
#
# When protected mode is on and if:
#
# 1) The server is not binding explicitly to a set of addresses using the
#    "bind" directive.
# 2) No password is configured.
#
# The server only accepts connections from clients connecting from the
# IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain
# sockets.
#
# By default protected mode is enabled. You should disable it only if
# you are sure you want clients from other hosts to connect to Redis
# even if no authentication is configured, nor a specific set of interfaces
# are explicitly listed using the "bind" directive.
protected-mode yes

# Accept connections on the specified port, default is 6379 (IANA #815344).
# If port 0 is specified Redis will not listen on a TCP socket.
port 6379

# TCP listen() backlog.
#
# In high requests-per-second environments you need an high backlog in order
# to avoid slow clients connections issues. Note that the Linux kernel
# will silently truncate it to the value of /proc/sys/net/core/somaxconn so
# make sure to raise both the value of somaxconn and tcp_max_syn_backlog
# in order to get the desired effect.
tcp-backlog 511

# Unix socket.
#
# Specify the path for the Unix socket that will be used to listen for
# incoming connections. There is no default, so Redis will not listen
# on a unix socket when not specified.
#
# unixsocket /tmp/redis.sock
# unixsocketperm 700

# 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 #####################################

# By default Redis does not run as a daemon. Use 'yes' if you need it.
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
daemonize yes

# If you run Redis from upstart or systemd, Redis can interact with your
# supervision tree. Options:
#   supervised no      - no supervision interaction
#   supervised upstart - signal upstart by putting Redis into SIGSTOP mode
#   supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET
#   supervised auto    - detect upstart or systemd method based on
#                        UPSTART_JOB or NOTIFY_SOCKET environment variables
# Note: these supervision methods only signal "process is ready."
#       They do not enable continuous liveness pings back to your supervisor.
supervised no

# If a pid file is specified, Redis writes it where specified at startup
# and removes it at exit.
#
# When the server runs non daemonized, no pid file is created if none is
# specified in the configuration. When the server is daemonized, the pid file
# is used even if not specified, defaulting to "/var/run/redis.pid".
#
# Creating a pid file is best effort: if Redis is not able to create it
# nothing bad happens, the server will start and run normally.
pidfile /var/run/redis_6379.pid

# Specify the server verbosity level.
# This can be one of:
# 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

# Specify the log file name. Also the empty string can be used to force
# Redis to log on the standard output. Note that if you use standard
# output for logging but daemonize, logs will be sent to /dev/null
logfile ""

# To enable logging to the system logger, just set 'syslog-enabled' to yes,
# and optionally update the other syslog parameters to suit your needs.
# syslog-enabled no

# Specify the syslog identity.
# syslog-ident redis

# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7.
# syslog-facility local0

# Set the number of databases. The default database is DB 0, you can select
# a different one on a per-connection basis using SELECT <dbid> where
# dbid is a number between 0 and 'databases'-1
databases 16

################################ SNAPSHOTTING  ################################
#
# Save the DB on disk:
#
#   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:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed
#
#   Note: you can disable saving completely by commenting out all "save" lines.
#
#   It is also possible to remove all the previously configured save
#   points by adding a save directive with a single empty string argument
#   like in the following example:
#
#   save ""


save 900 1
save 300 10
save 60 10000

# By default Redis will stop accepting writes if RDB snapshots are enabled
# (at least one save point) and the latest background save failed.
# This will make the user aware (in a hard way) that data is not persisting
# on disk properly, otherwise chances are that no one will notice and some
# disaster will happen.
#
# If the background saving process will start working again Redis will
# automatically allow writes again.
#
# However if you have setup your proper monitoring of the Redis server
# and persistence, you may want to disable this feature so that Redis will
# continue to work as usual even if there are problems with disk,
# permissions, and so forth.
stop-writes-on-bgsave-error yes

# Compress string objects using LZF when dump .rdb databases?
# For default that's set to 'yes' as it's almost always a win.
# If you want to save some CPU in the saving child set it to 'no' but
# the dataset will likely be bigger if you have compressible values or keys.
rdbcompression yes

# Since version 5 of RDB a CRC64 checksum is placed at the end of the file.
# This makes the format more resistant to corruption but there is a performance
# hit to pay (around 10%) when saving and loading RDB files, so you can disable it
# for maximum performances.
#
# RDB files created with checksum disabled have a checksum of zero that will
# tell the loading code to skip the check.
rdbchecksum yes

# The filename where to dump the DB
dbfilename dump.rdb

# The working directory.
#
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
#
# The Append Only File will also be created inside this directory.
#
# Note that you must specify a directory here, not a file name.
dir ./

################################# REPLICATION #################################

# Master-Slave replication. Use slaveof to make a Redis instance a copy of
# another Redis server. A few things to understand ASAP about Redis replication.
#
# 1) Redis replication is asynchronous, 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>

# If the master is password protected (using the "requirepass" configuration
# directive below) it is possible to tell the slave to authenticate before
# starting the replication synchronization process, otherwise the master will
# refuse the slave request.
#
# masterauth <master-password>

# When a slave loses its connection with the master, or when the replication
# is still in progress, the slave can act in two different ways:
#
# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will
#    still reply to client requests, possibly with out of date data, or the
#    data set may just be empty if this is the first synchronization.
#
# 2) if slave-serve-stale-data is set to 'no' the slave will reply with
#    an error "SYNC with master in progress" to all the kind of commands
#    but to INFO and SLAVEOF.
#
slave-serve-stale-data yes

# You can configure a slave instance to accept writes or not. Writing against
# a slave instance may be useful to store some ephemeral data (because data
# written on a slave will be easily deleted after resync with the master) but
# may also cause problems if clients are writing to it because of a
# misconfiguration.
#
# Since Redis 2.6 by default slaves are read-only.
#
# Note: read only slaves are not designed to be exposed to untrusted clients
# on the internet. It's just a protection layer against misuse of the instance.
# Still a read only slave exports by default all the administrative commands
# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve
# security of read only slaves using 'rename-command' to shadow all the
# administrative / dangerous commands.
slave-read-only yes

# Replication SYNC strategy: disk or socket.
#
# -------------------------------------------------------
# WARNING: DISKLESS REPLICATION IS EXPERIMENTAL CURRENTLY
# -------------------------------------------------------
#
# New slaves and reconnecting slaves that are not able to continue the replication
# process just receiving differences, need to do what is called a "full
# synchronization". An RDB file is transmitted from the master to the slaves.
# The transmission can happen in two different ways:
#
# 1) Disk-backed: The Redis master creates a new process that writes the RDB
#                 file on disk. Later the file is transferred by the parent
#                 process to the slaves incrementally.
# 2) Diskless: The Redis master creates a new process that directly writes the
#              RDB file to slave sockets, without touching the disk at all.
#
# With disk-backed replication, while the RDB file is generated, more slaves
# can be queued and served with the RDB file as soon as the current child producing
# the RDB file finishes its work. With diskless replication instead once
# the transfer starts, new slaves arriving will be queued and a new transfer
# will start when the current one terminates.
#
# When diskless replication is used, the master waits a configurable amount of
# time (in seconds) before starting the transfer in the hope that multiple slaves
# will arrive and the transfer can be parallelized.
#
# With slow disks and fast (large bandwidth) networks, diskless replication
# works better.
repl-diskless-sync no

# When diskless replication is enabled, it is possible to configure the delay
# the server waits in order to spawn the child that transfers the RDB via socket
# to the slaves.
#
# This is important since once the transfer starts, it is not possible to serve
# new slaves arriving, that will be queued for the next RDB transfer, so the server
# waits a delay in order to let more slaves arrive.
#
# The delay is specified in seconds, and by default is 5 seconds. To disable
# it entirely just set it to 0 seconds and the transfer will start ASAP.
repl-diskless-sync-delay 5

# Slaves send PINGs to server in a predefined interval. It's possible to change
# this interval with the repl_ping_slave_period option. 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

# Disable TCP_NODELAY on the slave socket after SYNC?
#
# If you select "yes" Redis will use a smaller number of TCP packets and
# less bandwidth to send data to slaves. But this can add a delay for
# the data to appear on the slave side, up to 40 milliseconds with
# Linux kernels using a default configuration.
#
# If you select "no" the delay for data to appear on the slave side will
# be reduced but more bandwidth will be used for replication.
#
# By default we optimize for low latency, but in very high traffic conditions
# or when the master and slaves are many hops away, turning this to "yes" may
# be a good idea.
repl-disable-tcp-nodelay no

# Set the replication backlog size. The backlog is a buffer that accumulates
# slave data when slaves are disconnected for some time, so that when a slave
# wants to reconnect again, often a full resync is not needed, but a partial
# resync is enough, just passing the portion of data the slave missed while
# disconnected.
#
# The bigger the replication backlog, the longer the time the slave can be
# disconnected and later be able to perform a partial resynchronization.
#
# The backlog is only allocated once there is at least a slave connected.
#
# repl-backlog-size 1mb

# After a master has no longer connected slaves for some time, the backlog
# will be freed. The following option configures the amount of seconds that
# need to elapse, starting from the time the last slave disconnected, for
# the backlog buffer to be freed.
#
# A value of 0 means to never release the backlog.
#
# repl-backlog-ttl 3600

# The slave priority is an integer number published by Redis in the INFO output.
# It is used by Redis Sentinel in order to select a slave to promote into a
# master if the master is no longer working correctly.
#
# A slave with a low priority number is considered better for promotion, so
# for instance if there are three slaves with priority 10, 100, 25 Sentinel will
# pick the one with priority 10, that is the lowest.
#
# However a special priority of 0 marks the slave as not able to perform the
# role of master, so a slave with priority of 0 will never be selected by
# Redis Sentinel for promotion.
#
# By default the priority is 100.
slave-priority 100

# It is possible for a master to stop accepting writes if there are less than
# N slaves connected, having a lag less or equal than M seconds.
#
# The N slaves need to be in "online" state.
#
# The lag in seconds, that must be <= the specified value, is calculated from
# the last ping received from the slave, that is usually sent every second.
#
# This option does not GUARANTEE that N replicas will accept the write, but
# will limit the window of exposure for lost writes in case not enough slaves
# are available, to the specified number of seconds.
#
# For example to require at least 3 slaves with a lag <= 10 seconds use:
#
# min-slaves-to-write 3
# 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 masteer.
#
# 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.
#
# 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.

################################### LIMITS ####################################

# Set the max number of connected clients at the same time. By default
# this limit is set to 10000 clients, however if the Redis server is not
# able to configure the process file limit to allow for the specified limit
# the max number of allowed clients is set to the current file limit
# minus 32 (as Redis reserves a few file descriptors for internal uses).
#
# Once the limit is reached Redis will close all the new connections sending
# an error 'max number of clients reached'.
#
# maxclients 10000

# Don't use more memory than the specified amount of bytes.
# When the memory limit is reached Redis will try to remove keys
# according to the eviction policy selected (see maxmemory-policy).
#
# If Redis can't remove keys according to the policy, or if the policy is
# set to 'noeviction', Redis will start to reply with errors to commands
# that would use more memory, like SET, LPUSH, and so on, and will continue
# to reply to read-only commands like GET.
#
# This option is usually useful when using Redis as an LRU cache, or to set
# a hard memory limit for an instance (using the 'noeviction' policy).
#
# WARNING: If you have slaves attached to an instance with maxmemory on,
# the size of the output buffers needed to feed the slaves are subtracted
# from the used memory count, so that network problems / resyncs will
# not trigger a loop where keys are evicted, and in turn the output
# buffer of slaves is full with DELs of keys evicted triggering the deletion
# of more keys, and so forth until the database is completely emptied.
#
# In short... if you have slaves attached it is suggested that you set a lower
# limit for maxmemory so that there is some free RAM on the system for slave
# output buffers (but this is not needed if the policy is 'noeviction').
#
# maxmemory <bytes>

# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
# is reached. You can select among five behaviors:
#
# volatile-lru -> remove the key with an expire set using an LRU algorithm
# allkeys-lru -> remove any key according to the LRU algorithm
# volatile-random -> remove a random key 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 expire at all, just return an error on write operations
#
# 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 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 a bit more CPU. 3 is very fast but not very accurate.
#
# maxmemory-samples 5

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

# By default Redis asynchronously dumps the dataset on disk. This mode is
# good enough in many applications, but an issue with the Redis process or
# a power outage may result into a few minutes of writes lost (depending on
# the configured save points).
#
# The Append Only File is an alternative persistence mode that provides
# much better durability. For instance using the default data fsync policy
# (see later in the config file) Redis can lose just one second of writes in a
# dramatic event like a server power outage, or a single write if something
# wrong with the Redis process itself happens, but the operating system is
# still running correctly.
#
# AOF and RDB persistence can be enabled at the same time without problems.
# If the AOF is enabled on startup Redis will load the AOF, that is the file
# with the better durability guarantees.
#
# Please check http://redis.io/topics/persistence for more information.

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".

# appendfsync always
appendfsync everysec
# appendfsync no

# When the AOF fsync policy is set to always or everysec, and a background
# saving process (a background save or AOF log background rewriting) is
# performing a lot of I/O against the disk, in some Linux configurations
# Redis may block too long on the fsync() call. Note that there is no fix for
# this currently, as even performing fsync in a different thread will block
# our synchronous write(2) call.
#
# In order to mitigate this problem it's possible to use the following option
# that will prevent fsync() from being called in the main process while a
# BGSAVE or BGREWRITEAOF is in progress.
#
# This means that while another child is saving, the durability of Redis is
# the same as "appendfsync none". In practical terms, this means that it is
# possible to lose up to 30 seconds of log in the worst scenario (with the
# default Linux settings).
#
# If you have latency problems turn this to "yes". Otherwise leave it as
# "no" that is the safest pick from the point of view of durability.

no-appendfsync-on-rewrite no

# Automatic rewrite of the append only file.
# Redis is able to automatically rewrite the log file implicitly calling
# BGREWRITEAOF when the AOF log size grows by the specified percentage.
#
# This is how it works: Redis remembers the size of the AOF file after the
# latest rewrite (if no rewrite has happened since the restart, the size of
# the AOF at startup is used).
#
# This base size is compared to the current size. If the current size is
# bigger than the specified percentage, the rewrite is triggered. Also
# you need to specify a minimal size for the AOF file to be rewritten, this
# is useful to avoid rewriting the AOF file even if the percentage increase
# is reached but it is still pretty small.
#
# Specify a percentage of zero in order to disable the automatic AOF
# rewrite feature.

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# An AOF file may be found to be truncated at the end during the Redis
# startup process, when the AOF data gets loaded back into memory.
# This may happen when the system where Redis is running
# crashes, especially when an ext4 filesystem is mounted without the
# data=ordered option (however this can't happen when Redis itself
# crashes or aborts but the operating system still works correctly).
#
# Redis can either exit with an error when this happens, or load as much
# data as possible (the default now) and start if the AOF file is found
# to be truncated at the end. The following option controls this behavior.
#
# If aof-load-truncated is set to yes, a truncated AOF file is loaded and
# the Redis server starts emitting a log to inform the user of the event.
# Otherwise if the option is set to no, the server aborts with an error
# and refuses to start. When the option is set to no, the user requires
# to fix the AOF file using the "redis-check-aof" utility before to restart
# the server.
#
# Note that if the AOF file will be found to be corrupted in the middle
# the server will still exit with an error. This option only applies when
# Redis will try to read more data from the AOF file but not enough bytes
# will be found.
aof-load-truncated yes

################################ 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 node enable the cluster support uncommenting the following:
#
# 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 a 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.
#
# 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.

################################## 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.
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.
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.
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.
hash-max-ziplist-entries 512
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.
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-rewrite-incremental-fsync yes


单位配置

配置文件unit单位 对大小写不敏感

image-20230810141057778

包含

image-20230810123210011

网络 NETWORK

bind 127.0.0.1  # 绑定的IP
protected-mode yes # 保护模式
port 6379       # 端口设置

通用配置 GENERAL

daemonize yes  # 以守护进程运行

pidfile /var/run/redis_6379.pid   # 如果以后台方式运行 就要指定一个pid文件

# Specify the server verbosity level.
# This can be one of:
# 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   # 日志级别
logfile ""        # 日志文件位置名
databases 16      # 数据库数量 默认16个
always-show-log yes   # 是否总显示LOGO
 

快照 SNAPSHOTTING

持久化,在规定的时间内 执行了多少次操作,则会持久化到文件 .rdb .aof

redis 是内存数据库,如果没有持久化,南无数据断电及失

# 如果900秒内至少有一个key进行了修改 我们及进行持久化操作
save  900 1
# 如果300秒内 至少有10次修改 我们及进行持久化操作
save 300 10
# 如果60秒内 至少有10000 key进行了修改我们及进行持久化操作
save 60 10000
# 可以自定义


stop-writes-on-bgsave-error yes # 持久化如果出错了,是否还需要继续工作

rdbcompression yes    # 是否压缩rdb文件  需要消耗cpu资源


rdbchecksum yes   # 保存rdb文件的时候,进行错误检查校验

dir ./   # rdb文件保存目录

复制 REPLICATION 主从复制

安全 SECURITY

config get requirepass  # 获取redis密码
config set requirepass "123456"  # 设置redis密码
requirepass 123456  # 设置redis密码

限制 LIMITS

maxclients 10000  # 最大链接数量

maxmemory <bytes> # 最大内存数量


maxmemory-policy noeviction # 内存到上限后的处理策略

#volatile-lru:只对设置了过期时间的key进行LRU(默认值)
#allkeys-lru : 是从所有key里 删除 不经常使用的key
#volatile-random:随机删除即将过期key
#allkeys-random:随机删除
#volatile-ttl : 删除即将过期的
#noeviction : 永不过期,返回错误

aof配置 APPEND ONLY MODE 模式

appendonly no # 默认不开启aof模式 默认使用rdb方式持久化的,在大部分所有的情况下rdb够用了
appendfilename "appendonly.aof" # 持久化文件的名字

# appendfsync always    #每次修改都会 sync 消耗性能
appendfsync everysec  # 每秒执行一次 sync 可能会丢失这一秒的数据
# appendfsync no   # 不执行 sync 这个时候操作系统自己同步数据,速度最快
# Redis配置文件样例
 
# 单位注意事项:当需要内存大小时,可以指定,它以通常的形式 1k 5GB 4M 等等:
#
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
#
# 单位不区分大小写,所以 1GB 1Gb 1gB 都是一样的
 
 
 
############################### INCLUDES(包含) ##############################
#这在你有标准配置模板但是每个redis服务器又需要个性设置的时候很有用。等同import导入
# include /path/to/local.conf
# include /path/to/other.conf
 
 
 
 
############################## GENERAL(通配)##################################
 
# 是否在后台执行,yes:后台运行;no:不是后台运行(老版本默认)
daemonize no
 
 
# 当Redis以上述守护进程方式运行时,Redis默认会把进程文件写入/var/run/redis.pid文件
pidfile /var/run/redis.pid
 
 
# 是否开启保护模式。如配置里没有指定bind和密码。开启该参数后,redis只允许本地访问,拒绝外部访问
# 要是开启了密码和bind,可以开启。否则最好关闭,设置为no。
protected-mode yes
 
 
# Redis监听端口号,默认为6379,如果指定0端口,表示Redis不监听TCP连接
port 6379
 
 
# 只允许来自bind指定网卡的Redis请求。如没有指定,则可以接受来自任意一个网卡的Redis请求
# bind 127.0.0.1
 
 
#配置unix socket来让redis支持监听本地连接。
# unixsocket /var/run/redis/redis.sock
 
 
#配置unix socket使用文件的权限
# unixsocketperm 755
 
 
# 连接超时时间,单位秒;超过timeout,服务端会断开连接,为0则服务端不会主动断开连接,不能小于0
timeout 0
 
 
# tcp keepalive参数。如果设置不为0,就使用配置tcp的SO_KEEPALIVE值
# 使用keepalive有两个好处:
#  1) 检测挂掉的对端。降低中间设备出问题而导致网络看似连接却已经与对端端口的问题。
#  2) 在Linux内核中,设置了keepalive,redis会定时给对端发送ack。检测到对端关闭需两倍的设置值
tcp-keepalive 0
 
 
# 指定日志记录级别,四个级别:
# 1) debug:很多信息,方便开发、测试
# 2) verbose:许多有用的信息,但是没有debug级别信息多(默认)
# 3) notice:适当的日志级别,适合生产环境
# 4) warning:只记录非常重要/关键的消息
loglevel verbose
 
 
# 指定日志文件记录的位置。logfile “”:标准输出。则日志将会发送给/dev/null
logfile “”  
 
 
# 是否将日志输出到系统日志
# syslog-enabled no
 
 
# syslog的标识符。
# syslog-ident redis
 
 
# 日志的来源、设备;指定系统日志工具。必须是 USER 或介于 LOCAL0-LOCAL7 之间
# syslog-facility local0
 
 
# 数据库的数量,默认数据库为0。可通过”SELECT [index]“命令指定数据库
databases 16
 
 
 
 
 
########################### SNAPSHOTTING (快照方式)  ###########################
 
# 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
# 注释掉“save”这一行配置项就可以让保存数据库功能失效
# 900秒(15分钟)内至少1个key值改变(则进行数据库保存--持久化) 
# 300秒(5分钟)内至少10个key值改变(则进行数据库保存--持久化) 
# 60秒(1分钟)内至少10000个key值改变(则进行数据库保存--持久化)
save 900 1
save 300 10
save 60 10000
 
 
# 当RDB持久化出现错误后,是否依然进行继续进行工作,yes:不能进行工作,no:可以继续进行工作
# 可以通过info中的rdb_last_bgsave_status了解RDB持久化是否有错误
stop-writes-on-bgsave-error yes
 
 
# 指定存储至本地数据库时是否压缩数据,耗cpu资源,默认为yes,Redis采用LZF压缩
# 如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大
rdbcompression yes
 
 
# 保存rdb文件时,是否进行错误检查校验。
# 从rdb格式的第五个版本开始,在rdb文件的末尾会带上CRC64的校验和。这跟有利于文件的容错性
# 但是在保存rdb文件的时候,会有大概10%的性能损耗,如果你追求高性能,可以关闭该配置。
rdbchecksum yes
 
 
# 指定本地数据库文件名(rdb文件的名称),默认值为dump.rdb
dbfilename dump.rdb
 
 
# 数据目录,数据库的写入会在这个目录。rdb、aof文件也会写在这个目录
# 指定本地数据库存放目录(dump.rdb文件存放目录),rdb、aof文件也会写在这个目录
# 注意,这里只能指定一个目录,不能指定文件名(文件名由上一个dbfilename配置项指定)
dir ./
 
 
 
 
 
############################# REPLICATION(主从复制) #############################
 
 
# 主从复制。使用slaveof从 Redis服务器复制一个Redis实例。注意,该配置仅限于当前slave有效
# 设置当本机为slav服务时,设置master服务的ip地址及端口,Redis启动时,自动从master进行数据同步
# slaveof <masterip> <masterport>
 
 
# 如master设置了requirepass密码,slave用此选项指定master认证密码
# 下文的“requirepass”配置项可以指定密码
# masterauth <master-password>
 
 
# 从库同主机失去连接或者复制正在进行,从机库的两种运行方式
# 当slave与master之间的连接断开或slave正在与master进行数据同步时,如果有slave请求
# 1) yes:slave仍然响应请求,此时可能有问题
# 2) no:slave会返回"SYNC with master in progress"错误信息。但INFO和SLAVEOF命令除外。
slave-serve-stale-data yes
 
 
# 作为从服务器,默认情况下是只读的(yes),可以修改成NO,用于写(不建议)。
slave-read-only yes
 
 
# 是否使用socket方式复制数据。目前redis复制提供两种方式,disk和socket。如果新的slave连上来或# 者重连的slave无法部分同步,就会执行全量同步,master会生成rdb文件。
# 有2种方式:
#   1) disk:master创建一个新的进程把rdb文件保存到磁盘,再把磁盘上的rdb文件传递给slave。
#   2) socket:master创建一个新的进程,直接把rdb文件以socket的方式发给slave。
# disk方式时,当一个rdb保存的过程中,多个slave都能共享这个rdb文件。
# socket方式就得一个个slave顺序复制。在磁盘速度缓慢,网速快的情况下推荐用socket方式。
repl-diskless-sync no
 
 
# diskless复制的延迟时间,防止设置为0。一旦复制开始
# 节点不会再接收新slave的复制请求直到下一个rdb传输。所以最好等待一段时间,等更多的slave连上来
repl-diskless-sync-delay 5
 
 
# slave根据指定的时间间隔向服务器发送ping请求。默认10秒。
# repl-ping-slave-period 10
 
 
# 复制连接超时时间。master和slave都有超时时间的设置。
# master检测到slave上次发送的时间超过repl-timeout,即认为slave离线,清除该slave信息。
# slave检测到上次和master交互的时间超过repl-timeout,则认为master离线。
# 需注意repl-timeout需设置一个比repl-ping-slave-period更大的值,不然会经常检测到超时。
# repl-timeout 60
 
 
# 是否禁止复制tcp链接的tcp nodelay参数,默认是no,即使用tcp nodelay。
# 如master设置了yes,在把数据复制给slave时,会减少包的数量和更小的网络带宽。
# 但这也可能带来数据的延迟。默认我们推荐更小的延迟,但在数据量传输很大的场景下,建议选择yes。
repl-disable-tcp-nodelay no
 
 
# 复制缓冲区大小,这是一个环形复制缓冲区,用来保存最新复制的命令。
# 这样在slave离线时,无需完全复制master的数据,如果可以执行部分同步,只需把缓冲区的部分数据复制# 给slave,就能恢复正常复制状态。缓冲区的大小越大,slave离线的时间可以更长,复制缓冲区只有在有
# slave连接的时候才分配内存。没有slave的一段时间,内存会被释放出来,默认1m。
# repl-backlog-size 5mb
 
 
# master没有slave一段时间会释放复制缓冲区的内存,repl-backlog-ttl设置该时间长度。单位为秒
# repl-backlog-ttl 3600
 
 
# 当master不可用,Sentinel会根据slave的优先级选举一个master。
# 最低的优先级的slave,当选master。而配置成0,永远不会被选举。
slave-priority 100
 
 
# master停止写入的方式,健康的slave的个数小于N,mater就禁止写入。master最少得有多少个健康的
# slave存活才能执行写命令。这个配置虽然不能保证N个slave都一定能接收到master的写操作,
# 但能避免没有足够健康的slave时,master不能写入来避免数据丢失。设置为0是关闭该功能。
# min-slaves-to-write 3
 
 
# 延迟小于min-slaves-max-lag 秒的slave才认为是健康的slave。
# min-slaves-max-lag 10
 
 
 
 
 
############################## SECURITY(安全) ################################
 
# 配置redis连接认证密码
# 如果配置了,则客户端在连接Redis时需通过auth <password>命令提供密码(默认关闭)
# 注意:因为redis太快了,每秒可认证15w次密码,简单的很容易被攻破,最好使用一个更复杂的密码
# requirepass foobared
 
 
 
# 把危险的命令给修改成其他名称。比如CONFIG命令可以重命名为一个很难被猜到的命令
# 这样用户不能使用,而内部工具还能接着使用。
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
 
 
# 设置成一个空的值,可以禁止一个命令
# rename-command CONFIG ""
 
 
 
 
################################ LIMITS(限制)#################################
 
# 设置连上redis的最大客户端连接数量。默认10000。设置0表示不作限制。
# 超出此数,Redis会关闭新的连接并向客户端返回max Number of clients reached错误
# redis不区分连接是客户端连接还是内部打开文件或和slave连接等,故maxclients最小建议设置到32
# maxclients 10000
 
 
# 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中
# 当内存满了,配合maxmemory-policy策略进行处理
# 当此方法处理后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。
# maxmemory <bytes>
 
 
# 内存容量超过maxmemory后的处理策略如下几种策略:
#  1) volatile-lru:只对设置过期时间的key进行LRU算法删除(默认)
#  2) allkeys-lru:删除不经常使用的key
#  3) volatile-random:随机删除即将过期的key
#  4) allkeys->random:随机删除一个key
#  5) volatile-ttl:删除即将过期的的key
#  6) noeviction:不移除任何key,对于写命令返回报错
# maxmemory-policy volatile-lru
 
#
 
# lru检测的样本数。
# 使用lru或ttl淘汰算法,从需要淘汰的列表中随机选择sample个key,选出闲置时间最长的key移除。
# maxmemory-samples 3
 
 
 
 
 
 
########################## APPEND ONLY MODE (附加模式) ###########################
 
 
# AOF持久化,指定是否在每次更新操作后进行日志记录,默认redis是异步(快照)的把数据写入本地磁盘
# redis默认使用的是rdb方式持久化,此方式在许多应用中已足够用。
# 但redis如果中途宕机,会导致可能有几分钟的数据丢失,按照上面save条件来策略进行持久化
# Append Only File是另一种持久化方式,可提供更好的持久化特性。
# Redis会把每次写入的数据在接收后都写入appendonly.aof 文件
# 每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。
appendonly no
 
 
# 指定aof文件名,默认为appendonly.aof
# appendfilename appendonly.aof
 
 
 
# AOF持久化三种同步策略:
#   1) no:不同步(不执行fsync),数据不会持久化
#   2) always:每次有数据发生变化时都会写入appendonly.aof(慢,安全)
#   3) everysec:每秒同步一次到appendonly.aof,可能会导致丢失这1s数据(折中选择,默认值)
appendfsync everysec
 
 
 
# 在AOF重写或写入rdb文件时,会执行大量IO
# 对于everysec和always的AOF模式来说,执行fsync会造成阻塞过长时间
# yes:表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入
# 默认为no,建议yes。Linux的默认fsync策略是30秒。可能丢失30秒数据。
no-appendfsync-on-rewrite no
 
 
 
# AOF自动重写配置。当目前AOF文件大小超过上一次重写的aof文件大小的百分之多少进行重写
# 即当AOF文件增长到一定大小时,Redis能调用bgrewriteaof对日志文件进行重写。
# 当前AOF文件大小是上次日志重写得到AOF文件大小的二倍(设置为100)时,自动启动新的日志重写过程。
auto-aof-rewrite-percentage 100
 
 
# 设置允许重写的最小AOF文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写
auto-aof-rewrite-min-size 64mb
 
 
 
#aof文件可能在尾部是不完整的,当redis启动的时候,aof文件的数据被载入内存。重启可能发生在redis所在的主机操作系统宕机后,尤其在ext4文件系统没有加上data=ordered选项(redis宕机或者异常终止不会造成尾部不完整现象。)出现这种现象,可以选择让redis退出,或者导入尽可能多的数据。如果选择的是yes,当截断的aof文件被导入的时候,会自动发布一个log给客户端然后load。如果是no,用户必须手动redis-check-aof修复AOF文件才可以。
aof-load-truncated yes
 
 
 
 
 
############################ LUA SCRIPTING(LUA 脚本) ###########################
 
# 如果达到最大时间限制(毫秒),redis会记个log,然后返回error。当一个脚本超过了最大时限。
# 只有SCRIPT KILL和SHUTDOWN NOSAVE可以用。第一个可以杀没有调write命令的东西。
# 要是已经调用了write,只能用第二个命令杀。
lua-time-limit 5000
 
 
 
 
############################ REDIS CLUSTER(Redis集群) ###########################
 
# 集群开关,默认是不开启集群模式。
# cluster-enabled yes
 
 
# 集群配置文件的名称,每个节点都有一个集群相关的配置文件,持久化保存集群的信息。
# 这个文件无需手动配置,这个配置文件有Redis生成并更新,每个Redis集群节点需要一个单独的配置文件,# 请确保与实例运行的系统中配置文件名称不冲突
# cluster-config-file nodes-6379.conf
 
 
# 节点互连超时的阀值。集群节点超时毫秒数
# cluster-node-timeout 15000
 
 
# 在进行故障转移时,全部slave会请求申请为master,有些slave可能与master断开连接一段时间了,
# 导致数据过于陈旧,这种slave不该提升为master。该参数判断slave与master断线的时间是否过长。
# 判断方法是:比较slave断开连接的时间和
#   (node-timeout * slave-validity-factor) + repl-ping-slave-period
# 如果节点超时时间为三十秒, 并且slave-validity-factor为10
# 假设默认的repl-ping-slave-period是10秒,即如果超过310秒slave将不会尝试进行故障转移 
# cluster-slave-validity-factor 10
 
 
# master的slave数量大于该值,slave才能迁移到其他孤立master上,如这个参数若被设为2,
# 那么只有当一个主节点拥有2 个可工作的从节点时,它的一个从节点会尝试迁移。
# cluster-migration-barrier 1
 
 
# 默认情况下,集群全部的slot有节点负责,集群状态才为ok,才能提供服务。
# 设置为no,可以在slot没有全部分配的时候提供服务。
# 不建议打开该配置,这样会造成分区时,小分区的master一直在接受写请求,而造成很长时间数据不一致。
# cluster-require-full-coverage yes
 
 
 
 
 
 
############################## SLOW LOG (慢日志)#############################
 
# slog log是用来记录redis运行中执行比较慢的命令耗时。
# 当命令的执行超过了指定时间,就记录在slow log中,slog log保存在内存中,所以没有IO操作。
# 执行时间比slowlog-log-slower-than大的请求记录到slowlog里面,单位是微秒
# 所以1000000就是1秒。注意,负数时间会禁用慢查询日志,而0则会强制记录所有命令。
slowlog-log-slower-than 10000
 
 
# 慢查询日志长度。当一个新的命令被写进日志时,最老的那个记录会被删掉。
# 这个长度没有限制。只要有足够的内存就行。你可以通过 SLOWLOG RESET 来释放内存。
slowlog-max-len 1024
 
 
 
 
 
############################ VIRTUAL MEMORY( 虚拟内存) ###########################
 
 
 
# 指定是否启用虚拟内存机制,默认no,
# VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上(内存占用多,最好关闭)
# 访问多的页面由磁盘自动换出到内存中
vm-enabled no
 
 
# 虚拟内存文件位置,默认值为/tmp/redis.swap,不可多个Redis实例共享
# Redis交换文件最好的存储是SSD(固态硬盘)
vm-swap-file /tmp/redis.swap
 
 
# redis使用的最大内存上限,保护redis不会因过多使用物理内存影响性能
# 将大于vm-max-memory的数据存入虚拟内存,但无论设置多少,所有索引数据都是内存存储的(即keys)
# 当vm-max-memory设置为0时,所有value都存在于磁盘。默认值为0
vm-max-memory 0
 
 
# Redis swap文件分成了很多的page,一个对象可以保存在多个page上面
# 但一个page上不能被多个对象共享,vm-page-size是要根据存储的数据大小来设定的。
# 建议:
#    如果存储很多小对象,page大小设置为32或64字节;
#    如果存储很大的对象,则可以使用更大的page,如果不确定,就使用默认值
# 每个页面的大小设置为32字节
vm-page-size 32
 
 
# 设置swap文件中页面数量
# 由于页表(一种表示页面空闲或使用的bitmap)是存放在内存中的,在磁盘上每8个页将消耗1byte的内存
# swap空间总容量为 vm-page-size * vm-pages
vm-pages 134217728
 
 
 
# 设置访问swap文件的线程数,最后不要超过机器的核数
# 如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟,默认值为4
vm-max-threads 4
 
 
 
 
############################ ADVANCED CONFIG(高级配置) ###########################
 
 
# 哈希表中元素(条目)总个数<=512个,采用ziplist,否则使用hash
hash-max-zipmap-entries 512   
 
# 哈希表中每个value的长度<=64字节时,采用ziplist,否则使用hash
hash-max-zipmap-value 64     
 
 
 
 
# list元素<=512个,采用ziplist,否则用linkedlist
list-max-ziplist-entries 512
 
# list内某个元素大小<=64字节时,采用ziplist,否则用linkedlist 
list-max-ziplist-value 64
 
 
 
 
# set内元素数量<=512个,且都是整数型值,采用inset,否则使用hashtable
set-max-intset-entries 512
 
 
 
# zset内元素数量<=128个,采用ziplist,否则用skiplist跳表 
zset-max-ziplist-entries 128
 
# zset内某个元素大小<=64字节时,采用ziplist,否则用skiplist跳表 
zset-max-ziplist-value 64
 
 
 
# value大小 <= hll-sparse-max-bytes使用稀疏数据结构(sparse)
# value大小 > hll-sparse-max-bytes使用稠密的数据结构(dense)。
# 一个比16000大的value是几乎没用的,建议的value大概为3000。
# 如果对CPU要求不高,对空间要求较高的,建议设置到10000左右。
hll-sparse-max-bytes 3000
 
 
# Redis将在每100毫秒时使用1毫秒的CPU时间来对redis的hash表进行重新hash,可以降低内存的使用。
# 当你的使用场景中,有非常严格的实时性需要,不能够接受Redis时不时的对请求有2毫秒的延迟的话
# 把这项配置为no。如果没有这么严格的实时性要求,可以设置为yes,以便能够尽可能快的释放内存。
# 指定是否激活重置哈希,默认为开启
activerehashing yes
 
 
 
# 对客户端输出缓冲进行限制,可以强迫那些不从服务器读取数据的客户端断开连接
# 用来强制关闭传输缓慢的客户端。
# 对于normal client,第一个0表示取消hard limit,第二个0和第三个0表示取消soft limit
# normal client默认取消限制,因为如果没有寻问,他们是不会接收数据的。
client-output-buffer-limit normal 0 0 0
 
 
# 对于slave client和 MONITER client,如果client-output-buffer一旦超过256mb
# 又或者超过64mb持续60秒,那么服务器就会立即断开客户端连接。
client-output-buffer-limit slave 256mb 64mb 60
 
 
# 对于pubsub client,如果client-output-buffer一旦超过32mb,又或者超过8mb持续60秒,
# 那么服务器就会立即断开客户端连接。
client-output-buffer-limit pubsub 32mb 8mb 60
 
 
# redis执行任务的频率为1s除以hz。
hz 10
 
 
# 在AOF重写时,如果打开了aof-rewrite-incremental-fsync开关,系统会每32MB执行一次fsync。
# 这对于把文件写入磁盘是有帮助的,可以避免过大的延迟峰值。
aof-rewrite-incremental-fsync yes
 

redis持久化

面试的时候 持久化 都是重点!

Redis 是内存数据库,如果不将内存中的数据库状态保存到磁盘,那么一但服务器进程推出,服务器中的数据库状态也会消失。所以Redis提供了持久化功能!

rdb

什么是rdb

在主从复制中rdb就是备用了!在从机上面

rdb图解

只指定的时间间隔内存中的数据集 快照写入磁盘,也就是 行话讲的Snapsshot 快照 他恢复时是将快照文件直接读到内存中去的,

redis 会单独创建(fork) 一个子进程进行持久化,会先将数据写到一个临时文件中,待次九华过程都结束了再用临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的。这就确保了极高的性能。如果需要进行大规模数据的恢复,但对于数据恢复的完整性不是非常敏感,那么rdb方式要比AOF方式更加高效。rdb的缺点就是最后一次持久化后的数据可能丢失。我们默认使用的就是Rdb,一般情况下不需要修改这个配置!

rdb保存的文件是dump.rdb文件都是在我们的配置文件中的快照文件中配置的

触发机制

  • save 命令配置的规则

  • 执行flushall命令 也会触发我们的rdb规则

  • 退出redis也会产生一个rdb文件

恢复rdb文件

1、 只需要将rdb文件放在我们的redis文件目录下,redis启动的时候就会自动检查dump.rdb中的数据

2、 查看需要存在的位置 config get dir

几乎自己默认的配置就够用了但是我们还要去学习

优点

1、 适合大闺蜜的数据恢复!

2、 对数据完整性要求不高

缺点

1、 需要一定的时间间隔操作!如果redis意外宕机了,这个最后一次修改数据就没有了!

2、 fork进程的时候,会占用一定的内存空间!!

rof

是什么

image-20230810150019321

以日志的形式来记录每个写操作,将redis执行过的所有指令都记录下来(读操作不做记录),只许追加文件但不可以改写文件,redis启动之初会读取这个文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将指令从前到后执行一次以完成数据的恢复工作

Aof保存的是appendonly,aof文件

默认是不开启的 我们需要手动配置!我们只需要将appendonly 改为yes就开启了aof!

重启redis就可以生效了

如果rof文件有错误 redis是启动不起来的 我们需要修复aof文件

redis给我们提供了一个工具redis-checj-aof

redis-checj-aof --fix appendonly.aof

从写规则说明 aof默认文件无限追加,文件会越来越大

从写aof文件

如果aof文件大于64m 太大了! fork一个新的进程来将我们的文件进行从写

优点和错误

优点:

1、每一次修改都同步,文件的完整性会更加好

2、每秒同步一次,可能会丢失一秒的数据

3、 从不同步,效率最高

缺点:

1、对数据文件来说,aof远远大于rdb修复的速度也比rdb慢

2、Aof运行效率也要比rdb慢,所以我们redis默认的配置就是rdb持久化

image-20230810151438910

redis发布订阅

redis 发布订阅(pub/sub )是一种消息通讯模式 :发送者pub发送消息,订阅者sub接收消息。 微信 、微博、关注系统。

redis客户端可以订阅任意数量的频道

订阅/发布 消息图:

第一个:发送者、 第二个:频道 、第三个:消息订阅者

image-20230810152637704

下图展示了频道channel1,以及订阅这个频道的三个客户端——— client2、 client5、client1之间的关系

image-20230810153110438

当有新消息 publish 命令发送给贫道channel1时这个消息会发送给订阅他的三个客户端:

image-20230810153239080

命令

这些命令广泛用于即时通讯应用,比如网络聊天室(chatroom)和实时广播、实时体现等

序号 命令及描述
1 [PSUBSCRIBE pattern pattern ...] 订阅一个或多个符合给定模式的频道。
2 [PUBSUB subcommand argument [argument ...]] 查看订阅与发布系统状态。
3 PUBLISH channel message 将信息发送到指定的频道。
4 [PUNSUBSCRIBE pattern [pattern ...]] 退订所有给定模式的频道。
5 [SUBSCRIBE channel channel ...] 订阅给定的一个或多个频道的信息。
6 [UNSUBSCRIBE channel [channel ...]] 指退订给定的频道。

测试

image-20230811100152894


# 接收

127.0.0.1:6379> SUBSCRIBE lmq
Reading messages... (press Ctrl-C to quit)

1) "subscribe"
2) "lmq"
3) (integer) 1
4) "message"  # 消息
5) "lmq"      # 频道
6) "hello"    # 内容
7) "message"
8) "lmq"
9) "hello2"

# 发布

127.0.0.1:6379> PUBLISH lmq "hello"
(integer) 1
127.0.0.1:6379> PUBLISH lmq "hello2"
(integer) 1

原理

image-20230811100721842

1、 实时消息系统!

2、实时聊天!(频道当做聊天室,将信息回显给所有人)

3、订阅,关注系统都可以

稍微复杂的就使用 mq

redis主从复制

高可用:主从复制,哨兵模式

info replication 查看节点状态

image-20230811111025723

默认每一台都是主节点

在本地启动多个 一台电脑启动多个redis

优先更改 端口 保存的文件【pid文件 日志 rdb备份文件】

1主2从

临时配置

一般情况下只配置从机就可以了 找一个主节点就可以了

slaveof 127.0.0.1 6379


修改配置文件

replication [主机ip] [主机端口]

masterauth [主机密码]

主机写从机只能读

主机断开连接 从机依然连接到主机 主机回来了从机依然可以获取

如果是命令行配置的主从 这个从机重启后会变为主机只要变为从机数据立刻就会恢复

复制原理

slave 启动后 链接到master 后发出一条sync同步命令

master 接到命令启动后台的存盘进程,同时收集所有收到的用于修改数据集的命令,在后台进程执行完毕之后,master将传送整个数据文件到slave 并完成一次完全同步

全量复制 : 而slave服务在手机到数据库文件数据后将其加载到内存中。

增量复制: master继续将新的所有手机到的修改命令一次传给slave 完成同步

但是只要是重新连接master 一次完全同步(全量复制)将被自动执行

链接链接

image-20230811150711142

也可以完成主从复制(以上两种工作都不会使用)

如果主节点掉了 能不能出一个主节点

谋朝篡位

手动设置 slaveof no one 使自己成为主节点 其他节点手动连接过来

主节点从新启动变为光杆司令 要重新配置

哨兵模式(自动选取老大)

哨兵是一个独立的进程 它独立运行 其他原理是 哨兵通过发送命令,等待Redis服务器响应,从而监控运行对个Redis实例

image-20230811151537001image-20230811151859711

测试

目前一主二从

1、 配置哨兵设置文件 sentinel.conf

sentinel monitor myredis 127.0.0.1 6379 1

后面这个数字1 代表主机挂了slave投票看让谁成为主机票数量最多的就会成为主机

如果主机节点断开了 这个时候就会从从机中随机选择一个服务器(这里面有一个投票算法)

如果主机回来了只能归并下做从机

优点

1、 哨兵集群,基于主从复制,所有的主从复制配置它全有

2、 主从可以切换,故障可以转移,系统的可用性就会更好

3、 哨兵模式就是主从模式的生根剂,手动到自动,更加健壮!

缺点

1、 redis不好在线扩容了,集群一但达到上限,在线扩容就十分麻烦!

2、 实现哨兵模式的配置其实很麻烦,里面有很多选择!

哨兵模式的全部配置!

# Example sentinel.conf
# 哨兵sentinel实例运行的端口 默认26379
port 26379

# 哨兵sentinel的工作目录
dir /tmp

# 哨兵sentinel监控的redis主节点的 ip port
# master-name 可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
# quorum 配置多少个sentinel哨兵统一认为master主节点失联 那么这时客观上认为主节点失联了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 2

# 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
# 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd

# 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000

# 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,这个数字越小,完成failover所需的时间就越长,但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
# sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1

# 故障转移的超时时间 failover-timeout 可以用在以下这些方面:
#1. 同一个sentinel对同一个master两次failover之间的间隔时间。
#2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
#3.当想要取消一个正在进行的failover所需要的时间。 
#4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了
# 默认三分钟
# sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000

# SCRIPTS EXECUTION
#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
#对于脚本的运行结果有以下规则:
#若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
#若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
#如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
#一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
#通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,一个是事件的类型,一个是事件的描述。如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。

#通知脚本
# shell编程
# sentinel notification-script <master-name> <script-path>
sentinel notification-script mymaster /var/redis/notify.sh

# 客户端重新配置主节点参数脚本
# 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。
# 以下参数将会在调用脚本时传给脚本:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 目前<state>总是“failover”,
# <role>是“leader”或者“observer”中的一个。
# 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的
# 这个脚本应该是通用的,能被多次调用,不是针对性的。
# sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh # 一般都是由运维来配置!


社会程序员饱和了(初级和中级)

rerdis缓存穿透和雪崩

缓存穿透

缓存穿透

概念

缓存穿透的概念很简单,用户系那个查询一个数据,发现redis内存数据库中没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是就都去请求持久层数据库。就会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。

解决方案

布隆过滤器

布隆过滤器是一种数据结构,对说要可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免对底层存储系统的查询压力:

布隆过滤器

缓存空对象

当存储层不命中后,即使返回的空对象也将其缓存起来,同时设置一个过期时间,之后再访问个数据将会从缓存中获取,保护了后端数据源

缓存空对象

但这个方法纯在两个问题

1、 如果空值能够被缓存起来,这就意味着缓存需要更多空间存储更多键,因为这当中可能会有很多空值键;

2、 即使对空值设置了过期时间,还是会穿在缓存层和存储层的数据会有一段时间窗口不一致,这对需要保持一致性的业务会有影响。

缓存击穿(量太大,缓存过期!)

概述

这里需要注意和缓存击穿的区别,缓存击穿,这是指一个key非常热点,在不停的抗着高并发,高并发集中在一个点进行访问,当这个可以在失效的瞬间,持续的高并发就会穿破缓存,直接请求数据库,就想在屏幕上凿开了一个洞。

当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存会导致数据库瞬间压力过大

解决方案

设置热点数据永不过期

从缓存层面来讲,没有设置过期时间,所以不会出现热点key过期后产生的问题。

加互斥锁

分布式锁: 使用分布式锁,保证每个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高斌发的压力转移到了分布式锁,因此对分布式锁的考验很大。

缓存雪崩

概念

缓存雪崩 是指在某一时间段,缓存集中过期失效。redis宕机!

雪崩

解决方案

redis高可用

这个思想的含义是既然redis有可能挂掉,那么我们多加几台redis,这样一台挂掉之后其他的还可以继续工作,其实就是搭建的集群(异地多活)

限流降级

这个解决方案的思想是在缓存失效之后,通过加锁或者队列来控制数据库写缓存的线程数量。比如对某个key只运行一个线程查询和写缓存,其他线程等待。

数据预热

数据加热的含义就是在正式部署之前,我们先把可能的数据预选访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发预加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

posted @ 2023-08-07 09:43  吾执青剑向天涯  阅读(9)  评论(0编辑  收藏  举报