分布式文件存储与数据缓存 Redis高可用分布式实践(下)(四)

本文涉及的产品
云数据库 Redis 版,标准版 2GB
推荐场景:
搭建游戏排行榜
云原生内存数据库 Tair,内存型 2GB
简介: 分布式文件存储与数据缓存 Redis高可用分布式实践(下)(四)

11.7 哨兵监控故障转移监控

演示故障转移

#查看主节点所在端口6379进程的PID
[root@localhost src]# lsof -i:6379
#杀死主节点的redis服务模拟故障
[root@localhost src]# kill -9  PID

查看哨兵节点信息

[root@localhost src]# ./redis-cli -p 26379
127.0.0.1:26379> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=127.0.0.1:6381,slaves=5,sentinels=3

注意:

会发现主节点还没有切换过来,因为哨兵发现主节点故障并转移,需要一段时间。

重启6379节点

[root@localhost src]# ./redis-cli info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6381
master_link_status:down

该节点变为了从节点

6379节点的配置文件被改写

故障转移阶段,哨兵和主从节点的配置文件都会被改写

include /usr/local/redis/redis.conf
pidfile "/var/run/redis_6379.pid"
port 6379
dbfilename "dump6379.rdb"
# Generated by CONFIG REWRITE
daemonize yes
protected-mode no
appendonly yes
slowlog-max-len 1200
slowlog-log-slower-than 1000
save 5 1
user default on nopass ~* &* +@all
dir "/usr/local/redis"
replicaof 127.0.0.1 6381

结论

  • 哨兵系统中的主从节点,与普通的主从节点并没有什么区别,故障发现和转移是由哨兵来控制和完成的。
  • 哨兵节点本质上是redis节点,是redis节点的不同进程。
  • 每个哨兵节点,只需要配置监控主节点,便可以自动发现其他的哨兵节点和从节点。因为主节点中包含从节点的信息。
  • 在哨兵节点启动和故障转移阶段,各个节点的配置文件会被重写(config rewrite)。

11.8 Cluster模式概述

Redis有三种集群模式

  • 主从模式
  • Sentinel模式
  • Cluster模式

哨兵模式的缺点

缺点:

  • 当master挂掉的时候,sentinel 会选举出来一个 master,选举的时候是没有办法去访问Redis的,会存在访问瞬断的情况;
  • 哨兵模式,对外只有master节点可以写,slave节点只能用于读。尽管Redis单节点最多支持10W的QPS,但是在电商大促的时候,写数据的压力全部在master上。
  • Redis的单节点内存不能设置过大,若数据过大在主从同步将会很慢;在节点启动的时候,时间特别长;

Cluster模式概述

Redis集群是一个由多个主从节点群组成的分布式服务集群,它具有复制、高可用和分片特性。当缓存的数据特别大的时候建议使用Cluster模式。数据不大的情况下使用哨兵模式即可。

Redis集群的优点

  • Redis集群有多个master,可以减小访问瞬断问题的影响
  • Redis集群有多个master,可以提供更高的并发量 
  • Redis集群可以分片存储,这样就可以存储更多的数据

11.9 Cluster模式搭建

Redis的集群搭建最少需要3个master节点,我们这里搭建3个master,每个下面挂一个slave节点,总共6个Redis节点;

环境准备

第1台机器(纯净): 192.168.66.100  8001端口 8002端口
第2台机器(redis-2): 192.168.66.101  8001端口 8002端口
第3台机器(redis-3): 192.168.66.102  8001端口 8002端口

关闭三台虚拟机的防火墙

systemctl stop firewalld.service

将纯净虚拟机中的redis压缩文件上传到redis-2和redis-3虚拟机中

scp -r redis-6.2.6.tar.gz/ 192.168.66.101:$PWD
scp -r redis-6.2.6.tar.gz/ 192.168.66.102:$PWD

将redis-2和redis-3的压缩文件分别解压到/user/local下

tar -zxvf redis-6.2.6.tar.gz -C /usr/local

将redis-2和redis-3中解压后的文件进行编译

[root@localhost redis-6.2.6]# make

注意:文件的编译需要C语言环境。

#检查当前的虚拟机是否安装了C语言环境
gcc --version
#安装gcc
yum install -y gcc

将编译完的文件进行安装

[root@localhost redis-6.2.6]# make install

分别在三台机器的redis安装目录下创建文件夹redis-cluster

[root@localhost redis-6.2.6]# mkdir redis-cluster
#在文件夹下创建用于存放配置文件的文件夹
[root@localhost redis-cluster]# mkdir 8001
[root@localhost redis-cluster]# madir 8002

在纯净虚拟机中将redis的核心配置文件redis.conf拷贝到/redis-cluster/8001下

[root@localhost redis-6.2.6]# cp redis.conf redis-cluster/8001

修改8001下的redis.conf配置文件

#修改配置文件中的端口号为8001
port 8001
#开启守护线程(后台运行)
daemonize yes
#修改pidfile,pidfile参数用于指定一个文件路径,用于存储Redis服务器进程的PID(进程ID)
pidfile /var/run/redis_8001.pid
#指定数据文件存放位置,必须要指定不同的目录位置,不然会丢失数据
dir /usr/local/redis-6.2.6/redis-cluster/8001/
#启动集群模式
cluster-enabled yes
#集群节点信息文件,这里800x最好和port对应上
cluster-config-file nodes-8001.conf
# 节点离线的超时时间
cluster-node-timeout 5000
#去掉bind绑定访问ip信息
#bind 127.0.0.1
#关闭保护模式
protected-mode no
#启动AOF文件
appendonly yes

将该配置文件复制到8002目录下

[root@localhost 8001]# cp redis.conf ../8002
#将8001改为8002
:%s/8001/8002/g

将本机机器上的文件拷贝到另外两台机器上

# 第二台机器
[root@localhost 8001]# scp -r  redis.conf 192.168.66.101:$PWD
[root@localhost 8002]# scp -r  redis.conf 192.168.66.101:$PWD
#第三台机器
[root@localhost 8001]# scp -r  redis.conf 192.168.66.102:$PWD
[root@localhost 8002]# scp -r  redis.conf 192.168.66.102:$PWD

分别启动这6个redis实例

[root@localhost src]# ./redis-server ../redis-cluster/8001/redis.conf
[root@localhost src]# ./redis-server ../redis-cluster/8002/redis.conf

检查是否启动成功

ps -ef |grep redis

在纯净虚拟机使用redis-cli创建整个redis集群

[root@localhost src]# ./redis-cli --cluster create  --cluster-replicas 1 192.168.66.100:8001 192.168.66.100:8002 192.168.66.101:8001 192.168.66.101:8002 192.168.66.102:8001 192.168.66.102:8002
  • --cluster-replicas 1:表示1个master下挂1个slave; --cluster-replicas 2:表示1个master下挂2个slave。

查看帮助命令

src/redis‐cli --cluster help

参数:

  • create:创建一个集群环境host1:port1 ... hostN:portN
  • call:可以执行redis命令
  • add-node:将一个节点添加到集群里,第一个参数为新节点的ip:port,第二个参数为集群中任意一个已经存在的节点的ip:port
  • del-node:移除一个节点
  • reshard:重新分片
  • check:检查集群状态

验证集群 在纯净虚拟机连接任意一个客户端

[root@localhost src]# ./redis-cli -c -h 192.168.66.101 -p 8001
192.168.66.101:8001>

参数:

  • ‐c表示集群模式
  • -h指定ip地址
  • -p表示端口号

查看集群的信息

cluster info

11.10 Cluster模式原理

Redis Cluster将所有数据划分为16384个slots(槽位),每个节点负责其中一部分槽位。槽位的信息存储于每个节点中。只有master节点会被分配槽位,slave节点不会分配槽位。通过槽位就能直接定位到数据的存储的位置。当客户端连接到redis集群的时候,集群会返回给客户端一个槽位表并缓存到客户端本地,该表明确划分了各redis服务器数据的槽位范围,存储数据时通过槽位定位算法决定数据保存在哪个服务器上。

槽位定位算法: k1 = 127001

Cluster 默认会对 key 值使用 crc16 算法进行 hash 得到一个整数值,然后用这个整数值对 16384 进行取模来得到具体槽位。

HASH_SLOT = CRC16(key) % 16384

192.168.66.101:8001> set k1 v1
-> Redirected to slot [12706] located at 192.168.66.102:8001
OK
192.168.66.102:8001>

在101机器主节点上存储数据,返回槽位为12706,当前主节点切换为102表示该数据存储到了102机器上。

注意:

根据k1计算出的槽值进行切换节点,并存入数据。不在一个slot下的键值,是不能使用mget、mset等多建操作。

可以通过{}来定义组的概念,从而使key中{}内相同内容的键值对放到同一个slot中。

192.168.66.102:8001> mset k1{test} v1 k2{test} v2 k3{test} v3
-> Redirected to slot [6918] located at 192.168.66.101:8001
OK
192.168.66.101:8001> get k2{test}
"v2"

查看节点的信息

192.168.66.101:8001> cluster nodes

杀死Master节点

lsof -i:8001
kill -9 pid

当一个master死往后会重新选举产生一个master。

11.11 Java操作Redis集群

Jedis整合Redis

<dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.6.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
public class TestJedis {
    @Test
    public void testCluster() {
        //Set集合保存节点数据
        Set<HostAndPort> redisNodes = new HashSet<HostAndPort>();
        redisNodes.add(new HostAndPort("192.168.66.100",8001));
        redisNodes.add(new HostAndPort("192.168.66.100",8002));
        redisNodes.add(new HostAndPort("192.168.66.101",8001));
        redisNodes.add(new HostAndPort("192.168.66.101",8002));
        redisNodes.add(new HostAndPort("192.168.66.102",8001));
        redisNodes.add(new HostAndPort("192.168.66.102",8002));
        //构建redis集群实例,建立连接
        JedisCluster jedisCluster = new JedisCluster(redisNodes);
        //添加元素
        jedisCluster.set("name","zhangsan");
        //获取元素
        System.out.println(jedisCluster.get("name"));
    }
}

SpringBoot 整合 Redis

pom依赖

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

配置文件

##服务器
spring.redis.cluster.nodes=192.168.66.100:8001,192.168.66.100:8002,192.168.66.101:8001,192.168.66.101:8002,192.168.66.102:8001,192.168.66.102:8002
## 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=300
## Redis数据库索引(默认为0)
spring.redis.database=0
## 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
## 连接池中的最大空闲连接
spring.redis.pool.max-idle=100
## 连接池中的最小空闲连接
spring.redis.pool.min-idle=20
## 连接超时时间(毫秒)
spring.redis.timeout=60000
@SpringBootTest
class RedisApplicationTests {
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Test
    void test(){
        //添加值
        stringRedisTemplate.opsForValue().set("age","23");
        //获取值
        String age = stringRedisTemplate.opsForValue().get("age");
        System.out.println(age);
    }
}

十二、Redis企业级解决方案

12.1 Redis脑裂

什么是Redis的集群脑裂

Redis的集群脑裂是指因为网络问题,导致Redis Master节点跟Redis slave节点和Sentinel集群处于不同的网络分区,此时因为sentinel集群无法感知到master的存在,所以将slave节点提升为master节点。说白了就是sentinel向主节点“喊话”的时候,主节点因为网络的问题没有及时恢复,让sentinel误认为主节点已经挂了。又重新选举产生了新的主节点。

注意:

此时存在两个不同的master节点,就像一个大脑分裂成了两个。集群脑裂问题中,如果客户端还在基于原来的master节点继续写入数据,那么新的Master节点将无法同步这些数据,当网络问题解决之后,sentinel集群将原先的Master节点降为slave节点,此时再从新的master中同步数据,将会造成大量的数据丢失。

解决方案

redis.conf配置参数:

min-replicas-to-write 1
min-replicas-max-lag 5

参数:

  • 第一个参数表示最少的slave节点为1个
  • 第二个参数表示数据复制和同步的延迟不能超过5秒

配置了这两个参数:如果发生脑裂原Master会在客户端写入操作的时候拒绝请求。这样可以避免大量数据丢失。

12.2 缓存预热

缓存冷启动

因为浏览器请求数据时先到redis缓存中查找数据,假如缓存中没有数据就会访问数据库获取数据,那么并发量上来Mysql就裸奔挂掉了。

缓存冷启动场景

新启动的系统没有任何缓存数据,在缓存重建数据的过程中,系统性能和数据库负载都不太好,所以最好是在系统上线之前就把要缓存的热点数据加载到缓存中,这种缓存预加载手段就是缓存预热。

解决思路

  • 提前给redis中灌入部分数据,再提供服务
  • 如果数据量非常大,就不可能将所有数据都写入redis,因为数据量太大了,第一是因为耗费的时间太长了,第二根本redis容纳不下所有的数据
  • 需要根据当天的具体访问情况,实时统计出访问频率较高的热数据
  • 然后将访问频率较高的热数据写入redis中,肯定是热数据也比较多,我们也得多个服务并行读取数据去写,并行的分布式的缓存预热

12.3 缓存穿透

概念

缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。

解释:

缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。

解决方案

  1. 对空值缓存:如果一个查询返回的数据为空(不管数据是否存在),我们仍然把这个空结果缓存,设置空结果的过期时间会很短,最长不超过5分钟。
  2. 布隆过滤器:如果想判断一个元素是不是在一个集合里,一般想到的是将集合中所有元素保存起来,然后通过比较确定。

布隆过滤器

布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”。

注意:

布隆说不存在一定不存在,布隆说存在你要小心了,它有可能不存在。

代码实现布隆过滤器

<dependency>
   <groupId>cn.hutool</groupId>
   <artifactId>hutool-all</artifactId>
   <version>5.7.17</version>
</dependency>
// 初始化 注意 构造方法的参数大小10 决定了布隆过滤器BitMap的大小
    BitMapBloomFilter filter = new BitMapBloomFilter(10);
    filter.add("123");
    filter.add("abc");
    filter.add("ddd");
    boolean abc = filter.contains("abc");
    System.out.println(abc);

12.4 缓存击穿

概念

某一个热点 key,在缓存过期的一瞬间,同时有大量的请求打进来,由于此时缓存过期了,所以请求最终都会走到数据库,造成瞬时数据库请求量大、压力骤增,甚至可能打垮数据库。

解决方案

  1. 互斥锁:在并发的多个请求中,只有第一个请求线程能拿到锁并执行数据库查询操作,其他的线程拿不到锁就阻塞等着,等到第一个线程将数据写入缓存后,其他线程直接查询缓存。
  2. 热点数据不过期:直接将缓存设置为不过期,然后由定时任务去异步加载数据,更新缓存。
public String get(String key) throws InterruptedException {
     String value = jedis.get(key);
     // 缓存过期
     if (value == null){
       // 设置3分钟超时,防止删除操作失败的时候 下一次缓存不能load db
       Long setnx = jedis.setnx(key + "mutex", "1");
       jedis.pexpire(key + "mutex", 3 * 60);
       // 代表设置成功
       if (setnx == 1){
         // 数据库查询
         //value =  db.get(key);
         //保存缓存
         jedis.setex(key,3*60,"");
         jedis.del(key + "mutex");
         return value;
       }else {
         // 这个时候代表同时操作的其他线程已经load db并设置缓存了。 需要重新重新获取缓存
         Thread.sleep(50);
         // 重试
         return get(key);
       }
     }else {
       return value;
     }
   }

12.5 缓存雪崩

概念

缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。

缓存正常从Redis中获取,示意图如下:

缓存失效瞬间示意图如下:

 

解决方案

  • 过期时间打散:既然是大量缓存集中失效,那最容易想到就是让他们不集中生效。可以给缓存的过期时间时加上一个随机值时间,使得每个 key 的过期时间分布开来,不会集中在同一时刻失效。
  • 热点数据不过期:该方式和缓存击穿一样,也是要着重考虑刷新的时间间隔和数据异常如何处理的情况。
  • 加互斥锁: 该方式和缓存击穿一样,按 key 维度加锁,对于同一个 key,只允许一个线程去计算,其他线程原地阻塞等待第一个线程的计算结果,然后直接走缓存即可。
public Object GetProductListNew(String cacheKey) {
     int cacheTime = 30;
     String lockKey = cacheKey;
     // 获取key的缓存
     String cacheValue = jedis.get(cacheKey);
     // 缓存未失效返回缓存
     if (cacheValue != null) {
       return cacheValue;
     } else {
       // 枷锁
       synchronized(lockKey) {
         // 获取key的value值
         cacheValue = jedis.get(cacheKey);
         if (cacheValue != null) {
           return cacheValue;
         } else {
           //这里一般是sql查询数据
           // db.set(key)
           // 添加缓存
           jedis.set(cacheKey,"");
         }
       }
       return cacheValue;
     }
   }

注意:

加锁排队只是为了减轻数据库的压力,并没有提高系统吞吐量。

12.6 Redis开发规范

 

key设计技巧

  • 1、把表名转换为key前缀,如tag:
  • 2、把第二段放置用于区分key的字段,对应msyql中主键的列名,如user_id
  • 3、第三段放置主键值,如2,3,4
  • 4、第四段写存储的列名
user_id name age
1 张三 18
2 lisi 20

 

#  表名 主键 主键值 存储列名字
set user:user_id:1:name 张三
set user:user_id:1:age 20
#查询这个用户
keys user:user_id:9*

value设计

拒绝bigkey

防止网卡流量、慢查询,string类型控制在10KB以内,hash、list、set、zset元素个数不要超过5000。

命令使用

1、禁用命令

禁止线上使用keys、flushall、flushdb等,通过redis的rename机制禁掉命令,或者使用scan的方式渐进式处理。

2、合理使用select

redis的多数据库较弱,使用数字进行区分,很多客户端支持较差,同时多业务用多数据库实际还是单线程处理,会有干扰。

3、使用批量操作提高效率

  • 原生命令:例如mget、mset。
  • 非原生命令:可以使用pipeline提高效率。

注意:

但要注意控制一次批量操作的元素个数(例如500以内,实际也和元素字节数有关)。

4、不建议过多使用Redis事务功能

Redis的事务功能较弱(不支持回滚),而且集群版本(自研和官方)要求一次事务操作的key必须在一个slot上。

 

客户端使用

  1. Jedis :https://github.com/xetorthio/jedis 重点推荐
  2. Spring Data redis :https://github.com/spring-projects/spring-data-redis 使用Spring框架时推荐
  3. Redisson :https://github.com/mrniko/redisson 分布式锁、阻塞队列的时重点推荐

1、避免多个应用使用一个Redis实例

不相干的业务拆分,公共数据做服务化。

2、使用连接池

可以有效控制连接,同时提高效率,标准使用方式:

执行命令如下:
Jedis jedis = null;
try {
   jedis = jedisPool.getResource();
 //具体的命令
   jedis.executeCommand()
} catch (Exception e) {
   logger.error("op key {} error: " + e.getMessage(), key, e);
} finally {
 //注意这里不是关闭连接,在JedisPool模式下,Jedis会被归还给资源池。
 if (jedis != null)
     jedis.close();
}

12.7 数据一致性

缓存已经在项目中被广泛使用,在读取缓存方面,大家没啥疑问,都是按照下图的流程来进行业务操作。

缓存说明:

从理论上来说,给缓存设置过期时间,是保证最终一致性的解决方案。缓存过期的时间越短,越能保证数据的一致性。

三种更新策略

  1. 先更新数据库,再更新缓存
  2. 先删除缓存,再更新数据库
  3. 先更新数据库,再删除缓存

先更新数据库,再更新缓存

这套方案,大家是普遍反对的。为什么呢?

线程安全角度

同时有请求A和请求B进行更新操作,那么会出现

(1)线程A更新了数据库

(2)线程B更新了数据库

(3)线程B更新了缓存

(4)线程A更新了缓存

这就出现请求A更新缓存应该比请求B更新缓存早才对,但是因为网络等原因,B却比A更早更新了缓存。这就导致了脏数据,因此不考虑。

先删缓存,再更新数据库

该方案会导致不一致的原因是。同时有一个请求A进行更新操作,另一个请求B进行查询操作。那么会出现如下情形:

(1)请求A进行写操作,删除缓存 (2)请求B查询发现缓存不存在 (3)请求B去数据库查询得到旧值 (4)请求B将旧值写入缓存 (5)请求A将新值写入数据库

注意:

该数据永远都是脏数据。

 

这种情况存在并发问题吗?

(1)缓存刚好失效 (2)请求A查询数据库,得一个旧值 (3)请求B将新值写入数据库 (4)请求B删除缓存 (5)请求A将查到的旧值写入缓存

发生这种情况的概率又有多少?

发生上述情况有一个先天性条件,就是步骤(3)的写数据库操作比步骤(2)的读数据库操作耗时更短,才有可能使得步骤(4)先于步骤(5)。可是,大家想想,数据库的读操作的速度远快于写操作的,因此步骤(3)耗时比步骤(2)更短,这一情形很难出现。


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1月前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
这篇文章是关于如何在SpringBoot应用中整合Redis并处理分布式场景下的缓存问题,包括缓存穿透、缓存雪崩和缓存击穿。文章详细讨论了在分布式情况下如何添加分布式锁来解决缓存击穿问题,提供了加锁和解锁的实现过程,并展示了使用JMeter进行压力测试来验证锁机制有效性的方法。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
|
6天前
|
缓存 NoSQL Java
谷粒商城笔记+踩坑(12)——缓存与分布式锁,Redisson+缓存数据一致性
缓存与分布式锁、Redisson分布式锁、缓存数据一致性【必须满足最终一致性】
谷粒商城笔记+踩坑(12)——缓存与分布式锁,Redisson+缓存数据一致性
|
27天前
|
缓存 NoSQL Linux
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
|
1月前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
这篇文章介绍了如何在SpringBoot项目中整合Redis,并探讨了缓存穿透、缓存雪崩和缓存击穿的问题以及解决方法。文章还提供了解决缓存击穿问题的加锁示例代码,包括存在问题和问题解决后的版本,并指出了本地锁在分布式情况下的局限性,引出了分布式锁的概念。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
|
22天前
|
数据采集 分布式计算 并行计算
Dask与Pandas:无缝迁移至分布式数据框架
【8月更文第29天】Pandas 是 Python 社区中最受欢迎的数据分析库之一,它提供了高效且易于使用的数据结构,如 DataFrame 和 Series,以及大量的数据分析功能。然而,随着数据集规模的增大,单机上的 Pandas 开始显现出性能瓶颈。这时,Dask 就成为了一个很好的解决方案,它能够利用多核 CPU 和多台机器进行分布式计算,从而有效地处理大规模数据集。
47 1
|
27天前
|
运维 安全 Cloud Native
核心系统转型问题之分布式数据库和数据访问中间件协作如何解决
核心系统转型问题之分布式数据库和数据访问中间件协作如何解决
|
30天前
|
NoSQL Redis 数据库
Redis AOF重写问题之同一数据产生两次磁盘IO如何解决
Redis AOF重写问题之同一数据产生两次磁盘IO如何解决
Redis AOF重写问题之同一数据产生两次磁盘IO如何解决
|
1月前
|
存储 NoSQL Redis
Redis存储原理与数据模型
Redis存储原理与数据模型
|
20天前
|
Java 数据库连接 微服务
揭秘微服务架构下的数据魔方:Hibernate如何玩转分布式持久化,实现秒级响应的秘密武器?
【8月更文挑战第31天】微服务架构通过将系统拆分成独立服务,提升了可维护性和扩展性,但也带来了数据一致性和事务管理等挑战。Hibernate 作为强大的 ORM 工具,在微服务中发挥关键作用,通过二级缓存和分布式事务支持,简化了对象关系映射,并提供了有效的持久化策略。其二级缓存机制减少数据库访问,提升性能;支持 JTA 保证跨服务事务一致性;乐观锁机制解决并发数据冲突。合理配置 Hibernate 可助力构建高效稳定的分布式系统。
37 0
|
27天前
|
缓存 NoSQL 算法
【Azure Redis 缓存】Redis导出数据文件变小 / 在新的Redis复原后数据大小压缩近一倍问题分析
【Azure Redis 缓存】Redis导出数据文件变小 / 在新的Redis复原后数据大小压缩近一倍问题分析