当前位置: 首页 > wzjs >正文

全国房地产网站沈阳seo收费

全国房地产网站,沈阳seo收费,网站 html 作用,网站存储空间大小前言:此篇文章系本人学习过程中记录下来的笔记,里面难免会有不少欠缺的地方,诚心期待大家多多给予指教。 基础篇: Redis(一)Redis(二)Redis(三)Redis&#x…

 前言:此篇文章系本人学习过程中记录下来的笔记,里面难免会有不少欠缺的地方,诚心期待大家多多给予指教。


基础篇:

  1. Redis(一)
  2. Redis(二)
  3. Redis(三)
  4. Redis(四)
  5. Redis(五)
  6. Redis(六)
  7. Redis(七)
  8. Redis(八)

进阶篇:

  1. Redis(九)
  2. Redis(十)
  3. Redis(十一)
  4. Redis(十二)
  5. Redis(十三)
  6. Redis(十四)

接上期内容:上期完成了手写分布式锁的相关知识学习。下面学习RedLock(红锁)分布式锁(官方推荐),话不多说,直接发车。


一、RedLock定义

(一)、官方说明

官方链接:Distributed Locks with Redis | Docs


(二)、为啥学习?怎么产生

学习原因:假设线程1首先获取锁成功,将键值对写入 redis 的 master 节点,在 redis 将该键值对同步到 slave 节点之前,master 发生了故障;redis 触发故障转移,其中一个 slave 升级为新的 master,此时新上位的master并不包含线程1写入的键值对,因此线程 2 尝试获取锁也可以成功拿到锁,此时相当于有两个线程获取到了锁,可能会导致各种预期之外的情况发生,例如最常见的脏数据。


(三)、RedLock设计理念

假设我们有N个Redis主节点,例如 N = 5这些节点是完全独立的,我们不使用复制或任何其他隐式协调系统,为了取到锁客户端执行以下操作:

1获取当前时间,以毫秒为单位;
2依次尝试从5个实例,使用相同的 key 和随机值(例如 UUID)获取锁。当向Redis 请求获取锁时,客户端应该设置一个超时时间,这个超时时间应该小于锁的失效时间。例如你的锁自动失效时间为 10 秒,则超时时间应该在 5-50 毫秒之间。这样可以防止客户端在试图与一个宕机的 Redis 节点对话时长时间处于阻塞状态。如果一个实例不可用,客户端应该尽快尝试去另外一个 Redis 实例请求获取锁;
3客户端通过当前时间减去步骤 1 记录的时间来计算获取锁使用的时间。当且仅当从大多数(N/2+1,这里是 3 个节点)的 Redis 节点都取到锁,并且获取锁使用的时间小于锁失效时间时,锁才算获取成功;
4如果取到了锁,其真正有效时间等于初始有效时间减去获取锁所使用的时间(步骤 3 计算的结果)。
5如果由于某些原因未能获得锁(无法在至少 N/2 + 1 个 Redis 实例获取锁、或获取锁的时间超过了有效时间),客户端应该在所有的 Redis 实例上进行解锁(即便某些Redis实例根本就没有加锁成功,防止某些节点获取到锁但是客户端没有得到响应而导致接下来的一段时间不能被重新获取锁)。

二、RedLock落地实现(Redisson)

(一)、单机

①、导入依赖

        <dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.45.0</version></dependency>

②、编码实现

步骤省略,最终目录图:

SingleRedLockConfig类:

import com.fasterxml.jackson.databind.ObjectMapper;
import org.redisson.Redisson;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class SingleRedLockConfig {@Beanpublic Redisson redisson() {Config config = new Config();// 单机模式config.useSingleServer().setAddress("redis://192.168.40.128:6379").setPassword("root");// 设置 JSON 序列化编解码器config.setCodec(new JsonJacksonCodec(new ObjectMapper()));return (Redisson) Redisson.create(config);}
}

SingleRedLockDemoController类:

import com.nb.redisdemo.RedLockDemo.SinglePlayerDemo.service.SingleRedLockDemoService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class SingleRedLockDemoController {@Resourceprivate SingleRedLockDemoService singleRedLockDemoService;@GetMapping(value = "/inventory/saleByRedisson")public String sale(){return singleRedLockDemoService.saleByRedisson();}
}

SingleRedLockDemoService类:

import jakarta.annotation.Resource;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;@Service
public class SingleRedLockDemoService {@Resourceprivate StringRedisTemplate stringRedisTemplate;@Value("${server.port}")private String port;@Resourceprivate Redisson redisson;public String saleByRedisson() {String retMessage = "";String key = "redLock";RLock redissonLock = redisson.getLock(key);redissonLock.lock();try {//1 查询库存信息String result = stringRedisTemplate.opsForValue().get("inventory001");//2 判断库存是否足够int inventoryNumber = result == null ? 0 : Integer.parseInt(result);//3 扣减库存if (inventoryNumber > 0) {stringRedisTemplate.opsForValue().set("inventory001", String.valueOf(--inventoryNumber));retMessage = "成功卖出一个商品,库存剩余: " + inventoryNumber;System.out.println(retMessage);} else {retMessage = "商品卖完了,o(╥﹏╥)o";}} finally {// 如果是本线程且是获取锁成功,才可以解锁if (redissonLock.isHeldByCurrentThread() && redissonLock.isLocked()) {redissonLock.unlock();}}return retMessage + "\t" + "服务端口号:" + port;}
}

③、测试功能

单机测试:访问localhost:8088/inventory/saleByRedisson进行测试,测试结果:

Nginx + Jmeter压测:访问自己Nginx服务器IP+/inventory/saleByRedisson,测试结果:

单机测试通过。


(二)、多机

由于硬件关系,三台存放redis锁的机器部署在同一台服务器上,三台机器互不从属,都是master

①、修改yaml文件

##==========================RedLock分布式锁配置=====================
spring.redis.database=0
spring.redis.password=root
spring.redis.timeout=3000
spring.redis.mode=singlespring.redis.pool.conn-timeout=3000
spring.redis.pool.so-timeout=3000
spring.redis.pool.size=10spring.redis.single.address1=服务器ip:6379
spring.redis.single.address2=服务器ip:6380
spring.redis.single.address3=服务器ip:6381


②、编码实现

由于RedLock这个对象已经被遗弃了,所以使用MultiLock实现

步骤省略,最终项目目录:

MultiMachineRedLockConfig类:

import jakarta.annotation.Resource;
import org.apache.commons.lang.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@EnableConfigurationProperties(RedisProperties.class)
public class MultiMachineRedLockConfig {@ResourceRedisProperties redisProperties;@BeanRedissonClient redissonClient1() {Config config = new Config();String node = redisProperties.getSingle().getAddress1();node = node.startsWith("redis://") ? node : "redis://" + node;SingleServerConfig serverConfig = config.useSingleServer().setAddress(node).setTimeout(redisProperties.getPool().getConnTimeout()).setConnectionPoolSize(redisProperties.getPool().getSize()).setConnectionMinimumIdleSize(redisProperties.getPool().getMinIdle());if (StringUtils.isNotBlank(redisProperties.getPassword())) {serverConfig.setPassword(redisProperties.getPassword());}return Redisson.create(config);}@BeanRedissonClient redissonClient2() {Config config = new Config();String node = redisProperties.getSingle().getAddress2();node = node.startsWith("redis://") ? node : "redis://" + node;SingleServerConfig serverConfig = config.useSingleServer().setAddress(node).setTimeout(redisProperties.getPool().getConnTimeout()).setConnectionPoolSize(redisProperties.getPool().getSize()).setConnectionMinimumIdleSize(redisProperties.getPool().getMinIdle());if (StringUtils.isNotBlank(redisProperties.getPassword())) {serverConfig.setPassword(redisProperties.getPassword());}return Redisson.create(config);}@BeanRedissonClient redissonClient3() {Config config = new Config();String node = redisProperties.getSingle().getAddress3();node = node.startsWith("redis://") ? node : "redis://" + node;SingleServerConfig serverConfig = config.useSingleServer().setAddress(node).setTimeout(redisProperties.getPool().getConnTimeout()).setConnectionPoolSize(redisProperties.getPool().getSize()).setConnectionMinimumIdleSize(redisProperties.getPool().getMinIdle());if (StringUtils.isNotBlank(redisProperties.getPassword())) {serverConfig.setPassword(redisProperties.getPassword());}return Redisson.create(config);}
}

RedisPoolProperties类:

import lombok.Data;@Data
public class RedisPoolProperties {private int maxIdle;private int minIdle;private int maxActive;private int maxWait;private int connTimeout;private int soTimeout;/*** 池大小*/private  int size;}

RedisProperties类:

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix = "spring.redis", ignoreUnknownFields = false)
@Data
public class RedisProperties {private int database;/*** 等待节点回复命令的时间。该时间从命令发送成功时开始计时*/private int timeout;private String password;private String mode;/*** 池配置*/private RedisPoolProperties pool;/*** 单机信息配置*/private RedisSingleProperties single;}

RedisSingleProperties类:

import lombok.Data;@Data
public class RedisSingleProperties {private  String address1;private  String address2;private  String address3;
}

MultiMachineRedLockDemoController类:代码参考来源:Distributed locks and synchronizers - Redisson Reference Guide

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.redisson.RedissonMultiLock;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.UUID;
import java.util.concurrent.TimeUnit;@RestController
@Slf4j
public class MultiMachineRedLockDemoController {public static final String CACHE_KEY_RED_LOCK = "multiLock";@ResourceRedissonClient redissonClient1;@ResourceRedissonClient redissonClient2;@ResourceRedissonClient redissonClient3;@GetMapping(value = "/multiLock")public String getMultiLock() throws InterruptedException {String uuid = UUID.randomUUID().toString().replaceAll("-", "");String uuidValue = uuid + ":" + Thread.currentThread().getId();RLock lock1 = redissonClient1.getLock(CACHE_KEY_RED_LOCK);RLock lock2 = redissonClient2.getLock(CACHE_KEY_RED_LOCK);RLock lock3 = redissonClient3.getLock(CACHE_KEY_RED_LOCK);RedissonMultiLock redLock = new RedissonMultiLock(lock1, lock2, lock3);redLock.lock();try {System.out.println(uuidValue + "\t" + "---come in biz multiLock");try {TimeUnit.SECONDS.sleep(30);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(uuidValue + "\t" + "---task is over multiLock");} catch (Exception e) {e.printStackTrace();log.error("multiLock exception ", e);} finally {redLock.unlock();log.info("释放分布式锁成功key:{}", CACHE_KEY_RED_LOCK);}return "multiLock task is over  " + uuidValue;}}

 ③、测试功能

访问localhost:8088/multiLock,测试结果:

三台redis客户端以及程序后台都正常,测试通过。


三、Redisson源码分析

参考上章学习手写分布式锁的案例。看看Redisson是如何实现redis分布式锁的。

①、加锁

1、redisson新建锁的默认时间为30秒

2、尝试获取锁

如果锁不存在,则通过hset设置它的值,并设置过期时间

如果锁已存在,并且锁的是当前线程,则通过hincrby给数值递增1。

如果锁已存在,但并非本线程,则返回过期时间。


3、加锁成功后,开启监控(自动续期)

每隔10秒检查一下,如果客户端A还持有锁key,那么就会不断的延长锁key的生存时间,默认每次续命又从30秒新开始。


②、解锁


四、总结

RedLock 作为分布式锁的优秀解决方案,以其独特的设计理念和可靠的实现方式,为分布式系统中的数据一致性和并发控制提供了有力支持。从单机到多机的实现过程,我们看到了其在不同场景下的应用灵活性。通过对 Redisson 源码的分析,进一步了解了如何将 RedLock 的理论落地为高效的代码实践。在实际开发中,合理运用 RedLock 能够有效解决分布式系统中的诸多同步难题,提升系统的稳定性与可靠性,是每一位分布式系统开发者值得深入掌握的关键技术。


ps:努力到底,让持续学习成为贯穿一生的坚守。学习笔记持续更新中。。。。

http://www.dtcms.com/wzjs/244660.html

相关文章:

  • 做网站月收入多少百度在线问答
  • 企业网站建设代码seo怎么优化武汉厂商
  • 怎样用ps设计网站模板360指数查询工具
  • 哪些网站可以做海报热点的网络营销优化推广
  • 网站建设推广方案书seo黑帽技术工具
  • 有什么网站专做买生活污水设备上海单个关键词优化
  • 我做服装设计师的 求推荐资源网站windows优化大师好吗
  • 上海网站备案中国宣布疫情结束日期
  • 网络工作室有什么项目3seo
  • 手机网站建设报价多少优化网哪个牌子好
  • 网站建设及维护机南京seo排名优化公司
  • 咸阳免费做网站灰色推广引流联系方式
  • 临沂做网站建设的公司醴陵网站制作
  • 做网站维护的人叫啥交换链接营销
  • 如何做好外贸网站建设今日国际新闻最新消息事件
  • 布吉做棋牌网站建设搜索引擎大全全搜网
  • 贵州省城乡建设厅官网揭阳百度快照优化排名
  • 课程网站建设ppt模板百度推广客户端app
  • 海珠区做网站的公司淘宝运营培训课程免费
  • 重庆网站建设维护深圳百度快照优化
  • 长安网站建设费用武汉排名seo公司
  • 怎么创建自己的网站平台app长沙seo优化服务
  • 视频广告长春seo培训
  • b2c网站的主要类型应用商店下载安装
  • 网站中转页seo基础培训机构
  • 奥利奥广告策划书seo教程 百度网盘
  • 蚌埠网站优化制作公司重庆网络推广外包
  • 网站建设费用预算表、百度关键词怎么做
  • 平面设计网站建设微博推广价格表
  • 武汉设计网站建设外贸平台推广