锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

Redis

时间:2022-08-11 11:30:02 cn槽型连接器

Redis

一、简介

Redis(Remote Dictionary Server),也就是说,远程字典服务是一个支持网络,可以基于内存或可持续的开源日志类型Key-Value非关系型数据库(NoSql)

NoSQL最常见的解释是non-relationalNot Only SQL。大规模高并发SNS类型的web2.0纯动态网站已显得力不从心,出现了许多难以克服的问题,NoSQL数据库的产生是为了解决大规模数据型的挑战,特别是大数据应用问题。

NoSql数据库分类:

在这里插入图片描述

二、Linux环境下安装Redis

下载链接:https://github.com/redis/redis/archive/7.0.0.tar.gz

上传到Linux环境解压:

安装gcc:

安装所需的环境:

确认安装完成:

进入/usr/local/bin目录查看:

将redis.conf文件复制到/usr/local/bin目录下:

修改配置文件redis.conf,将其更改为后台启动:

通过指定的配置文件启动redis服务:

使用客户端测试连接:

查看redis进程:

关机命令:shutdown

三、性能测试

本机测试100连接数10000请求数:

参数列表:

四、基本命令

1.type

type 返回命令 key 存储值的类型。

2.keys

keys 命令用于找到符合给定模式的所有命令 pattern 的 key 。

keys *在数据库下搜索一切key值:

3.flushdb/flushall

flushdb 清空命令当前数据库的数据。

flushall 清空命令整个 Redis 服务器数据(删除所有数据库中的所有数据 key )。

4.rename

rename 修改命令 key 的名称 。

5.renamenx

renamenx 新的命令 key 不存在时修改 key 的名称 。

修改成功时,返回 1 。 如果新名已经存在,返回 0 。

6.exists

exists 命令用于检查给定 key 是否存在。

7.del

del 命令用于删除现有键。删除成功返回1,删除不存在的键 key返回0 。

8.select

select 命令用于切换到指定的数据库,数据库索引号 index 指定数字值,查看redis.conf文件,redis默认数据库数量为16,下标为0~15。

9.move

move 使用当前数据库的命令 key 移动到给定的数据库 db 当中。

10.randomkey

randomkey 命令从当前数据库中随机返回 key 。

当数据库不空时,返回一个 key 。 当数据库空时,返回 nil 。

11.expire/ttl

expire 设置命令 key 过期时间。key 过期后将不再可用。

设置成功返回 1 ,当 key 不存在返回 0 。

ttl 命令以秒为单位返回 key 剩余过期时间。

当 key 不存在时,返回 -2 。 当 key 当存在但未设定剩余生存时间时,返回 -1 。 否则,以毫秒为单位返回 key 剩余的生存时间。

12.persist

persist 命令用于删除给定 key 过期时间,使 key 永不过期。

当过期时间成功移除时,返回 1 。 如果 key 不存在或 key 过期时间没有设置,返回 0 。

五、Redis 数据类型

1.String(Key-Value)

  • set/get:

set 命令用于设置给定 key 的值。如果 key 其他值已存储, set 复制旧值,忽略类型。

get 命令用于获取指定 key 的值。如果 key 不存在,返回 nil 。如果key 储存的值不是字符串类型,返回一个错误。

  • setnx

setnx(SET if Not eXists) 命令在指定的 key 不存在时,为 key 设置指定值。

设置成功,返回 1 。 设置失败,返回 0 。

  • setex

setex 命令为指定的 key 假设值及其过期时间。 key 存在, setex 命令将取代旧值。

  • mset/mget

mset 命令用于同时设置一个或多个 key-value 对。

mget 命令返回所有(一个或多个) key 的值。 如果给定的 key 里面,有一个 key 不存在,所以这个 key 返回特殊值 nil 。

  • incr/decr:

incr 命令将 key 中存储的数字值增加,decr 命令将 key 中存储的数字值减一。

如果 key 不存在,所以 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。

如果值包含错误的类型,或者字符串类型的值不能表示为数字,则返回错误。

操作值限制在 64 位(bit)有符号数字表示。

  • incrBy/decrBy

incrby 命令将 key 中间存储的数字加上指定的增量值, decrby 命令将 key 存储值减去指定的减量值。

  • strlen

strlen 命令用于获取指定 key 存储的字符串值的长度。

当 key 当不存储字符串值时,返回一个错误。 当 key 不存在时,返回 0。

  • setRange/getRange

setrange 命令用指定的字符串覆盖 key 存储的字符串值从偏移量覆盖的位置 offset 开始。

getrange 该命令用于获取指定的存储 key 中间字符串的子字符串。字符串的截取范围由字符串截取 start 和 end 两个偏移决定(包括两个偏移决定(包括) start 和 end 在内)。

  • append:

append 命令用于为指定的 key 追加值。

如果 key 已经存在并且是一个字符串, append 命令将 value 追加到 key 原来的值的末尾。

如果 key 不存在, append 就简单地将给定 key 设为 value ,就像执行 SET key value 一样。

  • msetnx

msetnx 命令用于所有给定 key 都不存在时,同时设置一个或多个 key-value 对。

当所有 key 都成功设置,返回 1 。 如果所有给定 key 至少有一个 key 已经存在,那么返回 0 。

  • getset

getset 命令用于设置指定 key 的值,并返回 key 旧的值。

当 key 没有旧值时,即 key 不存在时,返回 nil 。

2.Hash(Key-Map)

  • hset/hget

hset 命令用于为哈希表中的字段赋值 。

如果哈希表不存在,一个新的哈希表被创建并进行 hset 操作。

如果字段已经存在于哈希表中,旧值将被覆盖。

hget 命令用于返回哈希表中指定字段的值。

  • hmset/hmget

hmset 命令用于同时将多个 field-value (字段-值)对设置到哈希表中。

hmget 命令用于返回哈希表中,一个或多个给定字段的值。

  • hsetnx

hsetnx 命令用于为哈希表中不存在的的字段赋值 。

如果哈希表不存在,一个新的哈希表被创建并进行 hset 操作。

如果字段已经存在于哈希表中,操作无效

  • hexists

hexists 命令用于查看哈希表的指定字段是否存在。

如果哈希表含有给定字段,返回 1 。 如果哈希表不含有给定字段,或 key 不存在,返回 0 。

  • hincrby

hincrby 命令用于为哈希表中的字段值加上指定增量值。

增量也可以为负数,相当于对指定字段进行减法操作。

如果哈希表的 key 不存在,一个新的哈希表被创建并执行 hincrby 命令。

如果指定的字段不存在,那么在执行命令前,字段的值被初始化为 0 。

对一个储存字符串值的字段执行 hincrby 命令将造成一个错误。

本操作的值被限制在 64 位(bit)有符号数字表示之内。

  • hlen

hlen 命令用于获取哈希表中字段的数量。

当 key 不存在时,返回 0 。

  • hdel

hdel 命令用于删除哈希表 key 中的一个或多个指定字段,不存在的字段将被忽略。

  • hgetall/hkeys/hvals

hgetall 命令用于返回哈希表中,所有的字段和值。

hkeys 命令用于获取哈希表中的所有字段名,当 key 不存在时,返回一个空列表。

hvals 命令返回哈希表所有字段的值,当 key 不存在时,返回一个空表。

3.List

  • Lpush/Rpush

Lpush 命令将一个或多个值插入到列表头部。 Rpush 命令将一个或多个值插入到列表的尾部

如果 key 不存在,一个空列表会被创建并执行 Lpush 操作。

当 key 存在但不是列表类型时,返回一个错误。

  • Lpop/Rpop

Lpop 命令用于从列表头部移除一个或多个元素并返回移除的元素。

Rpop 命令用于从列表尾部移除一个或多个元素并返回移除的元素。

  • Lrange

Lrange 返回列表中指定区间内的元素,区间以偏移量 start 和 end 指定。

其中 0 表示列表的第一个元素,也可以使用负数下标,以 -1 表示列表的最后一个元素。

  • Llen:

Llen 命令用于返回列表的长度。

如果列表 key 不存在,则返回 0 。 如果 key 不是列表类型,返回一个错误。

  • Lindex

Lindex 命令用于通过索引获取列表中的元素。

也可以使用负数下标,以 -1 表示列表的最后一个元素。

  • Lset

Lset 通过索引来设置元素的值。

当索引参数超出范围,或对一个空列表进行 LSET 时,返回一个错误。

  • Lrem

Lrem 根据参数 count 的值,移除列表中与参数 value 相等的元素。

count > 0 : 从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count 。

count < 0 : 从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count 的绝对值。

count = 0 : 移除表中所有与 value 相等的值。

  • Linsert

Linsert 命令用于在列表的元素前或者后插入元素。

当指定元素不存在于列表中时,不执行任何操作。

当列表不存在时,被视为空列表,不执行任何操作。

如果 key 不是列表类型,返回一个错误。

  • Ltrim

Ltrim 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。

  • Rpoplpush

Rpoplpush 命令用于移除列表的最后一个元素,并将该元素添加到另一个列表并返回。

4.Set

  • Sadd

Sadd 命令将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略

假如集合 key 不存在,则创建一个只包含添加的元素作成员的集合。

当集合 key 不是集合类型时,返回一个错误。

  • Smembers

Smembers 命令返回集合中的所有的成员。 不存在的集合 key 被视为空集合。

  • Spop

Spop 命令用于移除并返回集合中的一个或多个随机元素。当集合不存在或是空集时,返回 nil 。

  • Srem

Srem 命令用于移除集合中的一个或多个指定元素,不存在的成员元素会被忽略。

  • Scard

Scard 命令返回集合中元素的数量。当集合 key 不存在时,返回 0 。

  • Sismember

Sismember 命令判断成员元素是否是集合的成员。

如果成员元素是集合的成员,返回 1 。 如果成员元素不是集合的成员,或 key 不存在,返回 0

  • Sunion

Sunion 命令返回给定集合的并集。不存在的集合 key 被视为空集。

  • Sdiff

Sdiff 命令返回给定集合之间的差集。不存在的集合 key 将视为空集。

  • Sinter

Sinter 命令返回给定所有给定集合的交集。 不存在的集合 key 被视为空集。 当给定集合当中有一个空集时,

结果也为空集。

  • Smove

Smove 命令将指定成员 member 元素从 source 集合移动到 destination 集合,是原子性操作。

如果 source 集合不存在或不包含指定的 member 元素,则 Smove 命令不执行任何操作,仅返回 0 。否

则, member 元素从 source 集合中被移除,并添加到 destination 集合中去。当 destination 集合已经包含

member 元素时, Smove 命令只是简单地将 source 集合中的 member 元素删除。当 source 或 destination

不是集合类型时,返回一个错误。

5.Zset(sorted set)

  • Zadd

Zadd 命令用于将一个或多个成员元素及其值加入到有序集当中。

如果某个成员已经是有序集的成员,那么更新这个成员的值,并通过重新插入这个成员元素,来保证该成员

在正确的位置上。分数值可以是整数值或双精度浮点数。如果有序集合 key 不存在,则创建一个空的有序集

并执行 ZADD 操作。当 key 存在但不是有序集类型时,返回一个错误。

  • Zrange:

Zrange 返回有序集中,指定区间内的成员。

其中成员的位置按分数值递增(从小到大)来排序。

具有相同分数值的成员按字典顺序来排列。

以 0 表示有序集第一个成员,以 -1 表示最后一个成员

加上rev 参数颠倒顺序,加上withscores带值显示

  • Zrevrange:

Zrevrange 命令返回有序集中,指定区间内的成员。

其中成员的位置按分数值递减(从大到小)来排列。


  • ZrangeByscore

Zrangebyscore 返回有序集合中指定分数区间的成员列表。

有序集成员按分数值递增(从小到大)次序排列。

默认情况下,区间的取值使用闭区间,通过给参数前增加 (变成开区间

  • ZrevrangeByscore:

Zrevrangebyscore 返回有序集中指定分数区间内的所有的成员。

有序集成员按分数值递减(从大到小)的次序排列。

  • Zcount:

Zcount 命令用于计算有序集合中指定分数区间的成员数量

  • Zcard:

Zcard 命令用于计算集合中元素的数量

  • Zrem:

Zrem 命令用于移除有序集中的一个或多个成员,不存在的成员将被忽略。

当 key 存在但不是有序集类型时,返回一个错误。

  • Zscore:

Zscore 命令返回有序集中,成员的分数值。

如果成员元素不是有序集 key 的成员,或 key 不存在,返回 nil 。

  • Zrank:

Zrank 返回有序集中指定成员的下标。

  • ZincrBy:

Zincrby 命令对有序集合中指定成员的分数加上增量 increment

可以通过传递一个负数值 increment ,让分数减去相应的值

当 key 不存在,或分数不是 key 的成员时等同于添加一个元素

6.Geospatial(地理位置)

  • Geoadd

将指定的地理空间位置(纬度、经度、名称)添加到指定的key中,这些数据将会存储到sorted set,实质上

为Zset类型,有效的经度从-180度到180度。有效的纬度从-85.05112878度到85.05112878度。当坐标位置超

出上述指定范围时,该命令将会返回一个错误。

  • Geopos:

key里返回所有给定位置元素的位置(经度和纬度)。

  • Geodist

返回两个给定位置之间的距离

如果两个位置之间的其中一个不存在, 那么命令返回空值。

如果用户没有显式地指定单位参数,默认使用米作为单位。

  • m 表示单位为米。
  • km 表示单位为千米。
  • mi 表示单位为英里。
  • ft 表示单位为英尺。

Geodist 命令在计算距离时会假设地球为完美的球形, 在极限情况下, 这一假设最大会造成 0.5% 的误差。

  • GeoRadiusByMember:

以给定的元素为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。

  • withdist: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。
  • withcoord: 将位置元素的经度和维度也一并返回。

命令默认返回未排序的位置元素。

通过以下两个参数, 用户可以指定被返回位置元素的排序方式:

  • asc: 根据中心的位置, 按照从近到远的方式返回位置元素。
  • desc: 根据中心的位置, 按照从远到近的方式返回位置元素。

7.hyperloglogs(基数统计)

Redis HyperLogLog 是用来做基数(不重复元素)统计的算法。

HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的,并且

是很小的。每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。存在

误差!!!

  • pfadd

pfadd 命令将所有元素参数添加到 HyperLogLog 数据结构中。

如果至少有一个元素被添加返回 1, 否则返回 0。

  • pfmerge

pfmerge 命令将多个 HyperLogLog 合并为一个 HyperLogLog ,合并后的 HyperLogLog 的基数估算值是通过对所有 给定 HyperLogLog 进行并集计算得出的。

  • pfcount

pfcount 命令返回给定 HyperLogLog 的基数估算值。

如果多个 HyperLogLog 则返回基数估值之和。

8.Bitmap(位图)

操作二进制0、1进行计数

  • setbit:

设置字符串某一位的值

  • bitcount

统计字符中每一位上值为1的个数

六、Redis事务和乐观

  • Multi:

Multi 命令用于标记一个事务块的开始。

事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由 exec命令执行

  • Exec:

Exec 命令用于执行所有事务块内的命令。当操作被打断时,返回空值 nil 。

  • Discard:

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

Redis没有隔离级别

Redis单条语句保证原子性,但是事务不保证原子性

Redis乐观锁使用Watch实现:

  • Watch

Watch 命令用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务

将被打断

  • Unwatch

Unwatch 命令用于取消 WATCH 命令对所有 key 的监视。

使用两个客户端连接redis

未使用乐观锁时:

使用乐观锁Watch

检测money被其他命令所改动,事务将被打断

七、SpringBoot整合

导入starter:

<dependency>
   <groupId>org.springframework.bootgroupId>
   <artifactId>spring-boot-starter-data-redisartifactId>
dependency>

配置:

spring:
  redis:
    host: localhost # 主机默认为本机
    port: 6379 # 默认端口为6379
    #password: 默认为空
    #client-type: jedis 设置客户端类型 默认为letture

1.Jedis

Jedis:直连,同步阻塞 IO,不支持异步,多线程不安全,需要使用Jedis pool使得在多线程下安

全,但函数与Redis命令一一对应方便理解

导入依赖:

<dependency>
   <groupId>redis.clientsgroupId>
   <artifactId>jedisartifactId>
   <version>4.2.2version>
dependency>
@SpringBootTest
public class JedisTest { 
         

    @Test
    void test(){ 
         
        //连接Redis
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        //jedis.auth("Your Password"); //检验Redis密码

        jedis.set("a", "1");
        System.out.println(jedis.get("a"));

        //关闭连接
        jedis.close();

    }
}

2.Letture

Letture:非阻塞的,采用Netty,在多线程中可以共享同一个连接

@SpringBootTest
public class RedisTest { 
         

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void test(){ 
         
        Group group = new Group("1", 10, "2020-1-1");
        redisTemplate.opsForValue().set("姓名", "张三");
        redisTemplate.opsForValue().set("性别", "男");
        redisTemplate.opsForValue().set("年龄", 18);
        redisTemplate.opsForValue().set("group", group);
        System.out.println(redisTemplate.opsForValue().get("姓名"));
        System.out.println(redisTemplate.opsForValue().get("性别"));
        System.out.println(redisTemplate.opsForValue().get("年龄"));
        System.out.println(redisTemplate.opsForValue().get("group"));
    }
}

/* 张三 男 18 Group(name=1, userNum=10, time=2020-1-1) */

redis数据进制问题:

使用redis-cli --raw命令连接查看:

产生中文乱码,由于redisTemplate将序列化后的值存入redis中造成

解决方法:

@Configuration
public class RedisConfig { 
         

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { 
         
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        Jackson2JsonRedisSerializer objectJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

     //方法已过时
  	//objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        			    objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

        objectJackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);

        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);

        // value序列化方式采用jackson
        template.setValueSerializer(objectJackson2JsonRedisSerializer);

        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(objectJackson2JsonRedisSerializer);

        template.afterPropertiesSet();

        return template;
    }
}

八、持久化

1.RDB(Redis DataBase)

在指定时间间隔内将内存中的数据写入磁盘中,即Snapshot快照

Redis会(fork)创建一个子进程来进行持久化,将数据写入一个临时文件(dump.rdb),待所有数据都写入后,将

这个文件替换上一次的文件。在此过程中,主进程不进行任何IO操作,保证了极高的性能。但是,如果持久

化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。Redis默认使用RDB持久化。

默认存储文件名

触发RDB持久化条件:

  1. save规则满足
  2. 执行flushall命令
  3. 退出redis(shutdown)

2.AOF(Append Only File)

将Redis执行过程中每一个写操作记录下来,每次进行追加,Redis启动会读取该文件(appendonly.aof)重新构

建数据,即将每一个写操作执行一遍。

测试aof:

aof文件破坏后无法连接redis:

可以通过redis-check-aof进行修复,可能会丢失少量数据:

AOF存储的文件远大于RDB,但修复速度比RDB慢,运行效率也相对低一些

九、发布与订阅

  • Subscribe

Subscribe 命令用于订阅给定的一个或多个频道的信息。

  • Publish

Publish 命令用于将信息发送到指定的频道。

十、主从复制,读写分离

指一台Redis服务器上的数据复制到其他的Redis服务器上,前者称为主节点(master),后者称为

从节点(slave),只能从主节点到从节点,主节点负责写入数据,从节点负责读取数据

主要作用:

  1. 数据冗余
  2. 故障恢复
  3. 负载均衡
  4. 高可用

一般Redis运用中,只使用一台Redis是不行的:

1.单个Redis服务器会发生单点故障,并且一台服务器需要处理所有请求,压力太大

2.单个Redis服务器内存容量有限,一般最大使用内存不应该超过20G

默认每一台Redis服务器都是主节点,一个主节点可以有多个从节点,但每个从节点只能有一个

主节点。

使用info replication查看节点信息:

搭建Redis伪集群,一个主节点加两个从节点:

复制三份redis配置文件:

修改配置文件:

注意

如果主机配置了密码,需要修改masterauth password

运行Redis服务:

设置主节点:

也可以在配置文件中设置:

主节点:

主节点负责写入数据,从节点负责读取数据

主节点断开后,从节点依旧连接主节点但是无法进行写操作:

主机恢复后,依旧为主节点,写入的数据从节点也能获取到

主从复制原理

从节点连接到主节点时会发送一个同步命令(sync),主节点将所有写操作命令持久化到文件,然

后将这个文件发送到从节点完成一次同步。

全量复制:从节点接受数据库文件后,将数据加载进内存中

增量复制:主节点将新的写入操作依次发送给从节点

当从节点重新连接到主机节点时,发生一次全量复制。

十一、哨兵模式

通过发送心跳命令监控节点是否正常运行,当主节点宕机后,选取其从节点变成新的主节点,保

证Redis的高可用

新建一个哨兵配置文件sentinel.conf:

# 哨兵监控本机6379端口 
# 1代表只有一个以上的哨兵认为主服务器不可用的时候,才会进行failover操作(一般设置为哨兵数量的一半加一)
sentinel monitor master 127.0.0.1 6379 1 
sentinel auth-pass master YourPassword # 如果节点设置了密码需要配置

主节点宕机后,选举出新的主节点

当进行failover操作后,配置文件会自动修改并记录信息

# 哨兵监听的端口变为6380,即当前的主节点
sentinel monitor master 127.0.0.1 6380 1
sentinel auth-pass master YourPassword 
# Generated by CONFIG REWRITE
latency-tracking-info-percentiles 50 99 99.9
dir "/usr/local/bin"
protected-mode no
port 26379
user default on nopass sanitize-payload ~* &* +@all
sentinel myid 2bd96303e14b6e137d479c0dc04d53aec4edd303
sentinel config-epoch master 2
sentinel leader-epoch master 2
sentinel current-epoch 2

# 原来的主节点变成从节点
sentinel known-replica master 127.0.0.1 6379
sentinel known-replica master 127.0.0.1 6381

十二、Cluster集群

主从集群可以解决该并发读的问题,但是没有解决大量数据存储,由于只有主节点能进行写操作,并发写的

问题没有解决,这时需要使用cluster集群。

cluster集群中有多个master保存不同的数据,每个master有多个slave,master之间使用ping检测健康状态,

客户端可以访问任意节点,最后都会被转发到正确的节点上。所有主节点一起划分16384个插槽,数据存放

在插槽中,随着插槽移动。

搭建单节点cluster集群:

redis配置文件,每台redis只需将文件中所有的7000修改为对应的端口号:

bind 0.0.0.0
# 端口
port 7000
# 后台启动
daemonize yes
# 设置数据库个数为1
databases 1
# 关闭保护模式,让外部redis客户端访问
protected-mode no
pidfile /var/run/redis_7000.pid
# 日志存储目录及日志文件名
logfile "7000.log"
# rdb数据文件名
dbfilename "dump7000.rdb"
# rdb数据文件和aof数据文件的存储目录
dir "/usr/local/bin/cluster"
# 是否开启aof
appendonly no
# 设置密码
requirepass 密码
# 从节点访问主节点密码(必须与 requirepass 一致)
masterauth 密码
# 是否开启集群模式,默认 no
cluster-enabled yes
# 集群节点信息文件,会保存在 dir 配置对应目录下
cluster-config-file nodes-7000.conf
# 集群节点连接超时时间
cluster-node-timeout 15000
#绑定ip 和 端口号
cluster-announce-ip 外网ip #!!!注意 声明节点ip为云服务器外网ip
cluster-announce-port 7000

依次启动redis:

printf '%s\n' 7000 7001 7002 7003 7004 7005 | xargs -I{ 
         } -t redis-server conf/cluster/{ 
         }/redis.conf

依次关闭redis:

printf '%s\n' 7000 7001 7002 7003 7004 7005 | xargs -I{ 
         } -t redis-cli -a 密码 -p { 
         } shutdown

创建cluster集群:

redis-cli -a 密码 --cluster create --cluster-replicas 1 外网IP:7000 外网IP:7001 外网IP:7002 外网IP:7003 外网IP:7004 外网IP:7005

在设置值和获取值的时候会自动转发到指定的节点上

springboot操作cluster集群:

spring:
  redis:
    password: 密码
    client-type: lettuce
    # cluster集群配置
    cluster:
      nodes: #指定分片集群地址
        - 服务器Ip:7000
        - 服务器Ip:7001
        - 服务器Ip:7002
        - 服务器Ip:7003
        - 服务器Ip:7004
        - 服务器Ip:7005
@RequestMapping("/redis")
@RestController
public class RedisController { 
         

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    @GetMapping("/set")
    public String set(String key, String value){ 
         
        if(!StringUtils.hasLength(key) || !StringUtils.hasLength(value))
        { 
         
            return "请输入key和value!!!";
        }

        stringRedisTemplate.opsForValue().set(key, value);
        return "success";
    }

    @GetMapping("/get")
    public String get(String key){ 
         
        if(!StringUtils.hasLength(key))
        { 
         
            return "请输入key!!!";
        }

        String s = stringRedisTemplate.opsForValue().get(key);
        return "key: " + key + ", value: " + s;
    }
}


集群伸缩:

十三、数据一致性

保证redis缓存内容和mysql数据库信息一致

1.更新缓存与删除缓存哪种方式更合适?

  • 更新缓存:

    优点:每次数据变化都及时更新缓存,所以查询时不容易出现未命中的情况。

    缺点:更新缓存的消耗比较大,影响服务器的性能。如果是写入数据频繁的业务场景,那么可能频繁的更新缓存时,却没有业务读取该数据。

  • 删除缓存

    优点:操作简单,无论更新操作是否复杂,都是将缓存中的数据直接删除。

    缺点:删除缓存后,下一次查询缓存会出现未命中,这时需要重新读取一次数据库。

从上面的比较来看,删除缓存是更优的方案。

2.先操作数据库还是缓存?

先删除缓存再更新数据库:

相关文章