哪些网站可以做旅游/媒体资源
一 分布式锁的概念
1:概念
分布式锁(多服务共享锁) 在分布式的部署环境下,通过锁机制来让多客户端互斥的对共享资源进行访问控制分布式系统不同进程共同访问共享资源的一种锁的实现。如果不同的系统或同一个系统的不同主机之间共享了某个临界资源,往往需要互斥来防止彼此干扰,以保证一致性。
2:锁/分布式锁/事务区别
- 锁 单进程的系统中,存在多线程同时操作一个公共变量,此时需要加锁对变量进行同步操作,保证多线程的操作线性执行消除并发修改。解决的是单进程中的多线程并发问题。
- 分布式锁 只要的应用场景是在集群模式的多个相同服务,可能会部署在不同机器上,解决进程间安全问题,防止多进程同时操作一个变量或者数据库。解决的是多进程的并发问题 事务 解决一个会话过程中,上下文的修改对所有数据库表的操作要么全部成功,要不全部失败。所以应用在service层。解决的是一个会话中的操作的数据一致性。
- 分布式事务 解决一个联动操作,比如一个商品的买卖分为添加商品到购物车、修改商品库存,此时购物车服务和商品库存服务可能部署在两台电脑,这时候需要保证对两个服务的操作都全部成功或者全部回退。解决的是组合服务的数据操作的一致性问题
3:reddison的公平锁
reddison公平锁枷锁
默认的加锁逻辑是非公平的。在加锁失败时,线程会进入 while 循环,一直尝试获得锁,这时候是多线程进行竞争。就是说谁抢到就是谁的。Redisson 提供了公平锁机制,使用方式如下
RLock fairLock = redisson.getFairLock("anyLock");
// 最常见的使用方法
fairLock.lock();
看门狗机制是在 RedissonBaseLock#scheduleExpirationRenewal 方法中,这块公平锁和非公平锁并无区别。前文已经了解到,公平锁加锁失败之后,会将当前放到等待队列中,通过 Java 代码中的循环不断尝试获得锁。
reddison公平锁释放
公平锁的释放同样分为主动释放和超时释放。
- 主动释放,即自己调用释放锁。
- 超时删除,则分为两种,一种是持锁线程超时删除,这种和非公平锁没有任何区别,因为这个锁也是含有超时时间+看门狗续租的。另一种则是等待队列中的超时删除,是在每次获取锁之前,判断第一个等待线程的时间戳是否超时,从而移除锁。
二 、使用的案例场景
需求
当在打车软件中,乘客下了订单。多个司机抢单,此时因为单子只有一个,多个司机对此共享资源进行抢,此处应该使用分布式锁;后台服务部署在多台服务器上;
controller层代码
@GetMapping("/do/{orderId}")public String grab(@PathVariable("orderId") int orderId, int driverId){System.out.println("order:"+orderId+",driverId:"+driverId);//此处调用锁控制层代码grabService.grabOrder(orderId,driverId);return "";}
锁控制层代码(使用synchronized 不成功)
使用synchronized 不能保证多台服务器只有一个抢成功;因为synchronized 只能锁本服务的资源;多台服务的资源是锁不住的;
@AutowiredOrderService orderService;@Overridepublic String grabOrder(int orderId, int driverId) {String lock = (orderId+"");synchronized (lock.intern()) {try {System.out.println("司机:"+driverId+" 执行抢单逻辑");//此处调用订单业务代码boolean b = orderService.grab(orderId, driverId);if(b) {System.out.println("司机:"+driverId+" 抢单成功");}else {System.out.println("司机:"+driverId+" 抢单失败");}} finally {}}return null;}
调用的订单业务代码
这一层就是写的伪代码,后续并不关注他
三、Redis解决方案-红锁
介绍
红锁本质上就是使用多个Redis做锁。例如有5个Redis,一次锁的获取,会对每个请求都获取一遍,如果获取锁成功的数量超过一半(2.5),则获取锁成功,反之失败;
释放锁也需要对每个Redis释放
红锁原理
- 在Redis的分布式环境中,我们假设有5个Redis master。这些节点完全互相独立,没有主从关系
- 线程1向这5个redis加锁,当加到第三个的时候,4和5加不上了;但是符合红锁的n/2+1原则,所以线程1获取到了锁;
- 当redis3挂了,此时线程1获取到了锁,正在顺序执行,
- 线程2来到了redis抢占锁,因为3挂了,1,2有锁,只有4和5可以加锁,因为我们注册的时候是5台,4和5这两台不满足n/2+1原则,抢占锁失败;
当锁遇到故障转移
单实例肯定不是很可靠吧?加锁成功之后,结果 Redis 服务宕机了,这不就凉凉~
这时候会提出来将 Redis 主从部署。即使是主从,也是存在巧合的!
主从结构中存在明显的竞态:
客户端 A 从 master 获取到锁在 master 将锁同步到 slave 之前,master 宕掉了。
slave 节点被晋级为 master 节点客户端 B 取得了同一个资源被客户端 A 已经获取到的另外一个锁。安全失效!有时候程序就是这么巧,比如说正好一个节点挂掉的时候,多个客户端同时取到了锁。如果你可以接受这种小概率错误,那用这个基于复制的方案就完全没有问题。
那我使用集群呢?如果还记得前面的内容,应该是知道对集群进行加锁的时候,其实是通过 CRC16 的 hash 函数来对 key 进行取模,将结果路由到预先分配过 slot 的相应节点上。
发现其实还是发到单个节点上的! 这时候 Redis 作者提出了 RedLock 的概念
总结一下就是对集群的每个节点进行加锁,如果大多数(N/2+1)加锁成功了,则认为获取锁成功。
RedLock 的问题
看着 RedLock 好像是解决问题了:
客户端 A 锁住了集群的大多数(一半以上);
客户端 B 也要锁住大多数;
这里肯定会冲突,所以 客户端 B 加锁失败。
那实际解决问题了么?
加锁 key 的问题
有一个很大的疑问,我加锁 lock1、lock2、lock3,但是 RedissonRedLock 是如何保证这三个 key 是在归属于 Redis 集群中不同的 master 呢?因为按照 RedLock 的理论,是需要在半数以上的 master 节点加锁成功。阅读完源码之后,发现 RedissonRedLock 完全是 RedissonMultiLock 的子类,只是重写了 failedLocksLimit 方法,保证半数以上加锁成功即可。所以这三个 key,是需要用户来保证分散在不同的节点上的。
红锁的争议
那我使用 5 个单节点的客户端,然后再使用红锁,听着好像是可以的,并且 RedissonRedLock 可以这样使用。但是那和 Redis 集群还有啥关系啊!所以依然没有解决我的问题,在 redis 集群下 针对master节点集群,,还是需要用户自己来“手工定位锁”,使锁的节点分散到不同的master 集群节点下。 手工定位锁,这个…… 我考虑了下,还是不用 RedLock 吧!如果master节点变动则锁也存在问题,master集群同步等等锁的同步和锁失效也是需要考虑的问题;
Redisson 的开发者认为 Redis 的红锁也存在争议(前文介绍的那个争议),但是为了保证可用性,RLock 对象执行的每个 Redis 命令执行都通过 Redis 3.0 中引入的 WAIT 命令进行同步。
Redisson 的开发者认为 Redis 的红锁也存在争议(前文介绍的那个争议),但是为了保证可用性,RLock 对象执行的每个
Redis 命令执行都通过 Redis 3.0 中引入的 WAIT 命令进行同步。
源码在这一部分。
看源码,同时发送了一个 WAIT 1 1000 到 Redis。
结论:Redisson RedLock 是基于联锁 MultiLock 实现的,但是使用过程中需要自己判断 key 落在哪个节点上,对使用者不是很友好。
红锁使用说明-官网介绍
基于Redis的Redisson红锁RedissonRedLock对象实现了Redlock介绍的加锁算法。该对象也可以用来将多个RLock对象关联为一个红锁,每个RLock对象实例可以来自于不同的Redisson实例。
RLock lock1 = redissonInstance1.getLock("lock1");
RLock lock2 = redissonInstance2.getLock("lock2");
RLock lock3 = redissonInstance3.getLock("lock3");RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
// 同时加锁:lock1 lock2 lock3
// 红锁在大部分节点上加锁成功就算成功。
lock.lock();
...
lock.unlock();
大家都知道,如果负责储存某些分布式锁的某些Redis节点宕机以后,而且这些锁正好处于锁住的状态时,这些锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。
另外Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。
RedissonRedLock lock = new RedissonRedLock(lock1, lock2, lock3);
// 给lock1,lock2,lock3加锁,如果没有手动解开的话,10秒钟后将会自动解开
lock.lock(10, TimeUnit.SECONDS);// 为加锁等待100秒时间,并在加锁成功10秒钟后自动解开
boolean res = lock.tryLock(100, 10, TimeUnit.SECONDS);
...
lock.unlock();
红锁实战
1.注册红锁的RedissonClient
@Component
public class RedisConfig {@Bean(name = "redissonRed1")@Primarypublic RedissonClient redissonRed1(){Config config = new Config();config.useSingleServer().setAddress("127.0.0.1:6379").setDatabase(0);return Redisson.create(config);}@Bean(name = "redissonRed2")public RedissonClient redissonRed2(){Config config = new Config();config.useSingleServer().setAddress("127.0.0.1:6380").setDatabase(0);return Redisson.create(config);}@Bean(name = "redissonRed3")public RedissonClient redissonRed3(){Config config = new Config();config.useSingleServer().setAddress("127.0.0.1:6381").setDatabase(0);return Redisson.create(config);}@Bean(name = "redissonRed4")public RedissonClient redissonRed4(){Config config = new Config();config.useSingleServer().setAddress("127.0.0.1:6382").setDatabase(0);return Redisson.create(config);}@Bean(name = "redissonRed5")public RedissonClient redissonRed5(){Config config = new Config();config.useSingleServer().setAddress("127.0.0.1:6383").setDatabase(0);return Redisson.create(config);}}
配置方式2
基于 Redis 的 Redisson 分布式联锁 RedissonMultiLock 对象可以将多个 RLock 对象关联为一个联锁,每个 RLock 对象实例可以来自于不同的 Redisson 实例。
按照官方文档的说法,这里 Redisson 客户端可以不是同一个。当然,一般工作中也不会说不用一个客户端吧,可以看出 遍历所有的锁,依次加锁。加锁逻辑就和可重入锁加锁并无区别了。所以 Lua 脚本就不进行分析了
2. 红锁使用
package com.online.taxi.order.service.impl;import com.online.taxi.order.constant.RedisKeyConstant;
import com.online.taxi.order.service.GrabService;
import com.online.taxi.order.service.OrderService;import org.redisson.Redisson;
import org.redisson.RedissonRedLock;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import java.util.concurrent.TimeUnit;@Service
public class GrabRedisRedissonRedLockLockServiceImpl implements GrabService {// 红锁@Autowired@Qualifier("redissonRed1")private RedissonClient redissonRed1;@Autowired@Qualifier("redissonRed2")private RedissonClient redissonRed2;@Autowired@Qualifier("redissonRed3")private RedissonClient redissonRed3;@Autowired@Qualifier("redissonRed4")private RedissonClient redissonRed4;@Autowired@Qualifier("redissonRed5")private RedissonClient redissonRed5;@AutowiredOrderService orderService;@Overridepublic String grabOrder(int orderId , int driverId){System.out.println("红锁实现类");//生成keyString lockKey = ("" + orderId).intern();//redisson锁 单节点
// RLock rLock = redissonRed1.getLock(lockKey);//红锁 redis sonRLock rLock1 = redissonRed1.getLock(lockKey);RLock rLock2 = redissonRed2.getLock(lockKey);RLock rLock3 = redissonRed3.getLock(lockKey);RLock rLock4 = redissonRed4.getLock(lockKey);RLock rLock5 = redissonRed5.getLock(lockKey);RedissonRedLock rLock = new RedissonRedLock(rLock1,rLock2,rLock3,rLock4,rLock5);try {/**红锁* waitTimeout 尝试获取锁的最大等待时间,超过这个值,则认为获取锁失败* leaseTime 锁的持有时间,超过这个时间锁会自动失效(值应设置为大于业务处理的时间,确保在锁有效期内业务能处理完)*/boolean b1 = rLock.tryLock((long)waitTimeout, (long)leaseTime, TimeUnit.SECONDS);if (b1){System.out.println("加锁成功");// 此代码默认 设置key 超时时间30秒,过10秒,再延时System.out.println("司机:"+driverId+" 执行抢单逻辑");boolean b = orderService.grab(orderId, driverId);if(b) {System.out.println("司机:"+driverId+" 抢单成功");}else {System.out.println("司机:"+driverId+" 抢单失败");}System.out.println("加锁成功");}else {System.out.println("加锁失败");}} finally {rLock.unlock();}return null;}}
四、单机版redission 使用
<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.18.0</version></dependency>
1.配置
@Value("${spring.redis.host}")private String url;@Value("${spring.redis.port}")private Integer port;@Value("${spring.redis.password}")private String password;@Beanpublic RedissonClient redissonClient(){// 配置Config config = new Config();log.info("Redisson 初始化 {}",String.format("redis://%s:%d",url,port));config.useSingleServer().setAddress(String.format("redis://%s:%d",url,port) ).setPassword(password);// 创建RedissonClient对象return Redisson.create(config);}
2. 注入分布式锁
此处枷锁后在释放锁是解决了锁的读写机制问题
@Autowired
private RedissonClient redissonClient;public List<? extends Object> getCachedConfigList(String ode) {List<StructureVo> configuration =null;String key = getCacheKey(orgCode, STR_CONFIG_LIST);List<Object> cacheConfig = redisCache.getCacheList(key);if (!CollectionUtils.isEmpty(cacheConfig)) {return cacheConfig;}RLock lock = redissonClient.getLock(getReddisonEbomCacheKey());try {lock.lock(DEFAULT_EXPIRE_SECOND,TimeUnit.SECONDS);List<Object> secondCacheConfig = redisCache.getCacheList(key);if (!CollectionUtils.isEmpty(secondCacheConfig)) {log.info("second lock reddison 查询到缓存释放锁!");reddisnUnlock(getReddisonEbomCacheKey());return cacheConfig;}log.info("reddison枷锁成功!存放缓存资源!");configuration = this.queryAllConfiguration();redisCache.setCacheList(key, configuration);redisCache.expire(key, DEFAULT_EXPIRE_HOURS, TimeUnit.HOURS);} catch (Exception e) {log.error("Happen Exception: " + e.getMessage(),e);}finally {reddisnUnlock(getReddisonEbomCacheKey());}return configuration;}
释放锁方法
private void reddisnUnlock(String key) {log.info(" reddison key {}锁释放!",key);try {RLock unlock = redissonClient.getLock(key);if (unlock != null && unlock.isHeldByCurrentThread()) {unlock.unlock();}} catch (IllegalMonitorStateException e) {log.info("reddison锁释放 Exception: " + e.getMessage(),e);}}
Redis 单实例版本锁 NX
单实例加锁
SET resource_name my_random_value NX PX 30000
对于单实例 Redis 只需要使用这个命令即可。
- NX:仅在不存在 key 的时候才能被执行成功;
- PX:失效时间,传入 30000,就是 30s 后自动释放锁;
- my_random_value:就是随机值,可以是线程号之类的。主要是为了更安全的释放锁,释放锁的时候使用脚本告诉 Redis: 只有 key 存在并且存储的值和我指定的值一样才能删除成功。
简单描述即为
- 指定一个 key 作为锁标记,存入 Redis 中,指定一个 唯一的用户标识作为 value。
- 当 key 不存在时才能设置值,确保同一时间只有一个客户端进程获得锁,满足互斥性特性。
- 设置一个过期时间,防止因系统异常导致没能删除这个 key,满足防死锁特性。
- 当处理完业务之后需要清除这个 key 来释放锁,清除 key 时需要校验 value 值,需要满足只有加锁的人才能释放锁
可以通过以下 Lua 脚本实现锁释放:
if redis.call("get",KEYS[1]) == ARGV[1] thenreturn redis.call("del",KEYS[1])
elsereturn 0
end
为什么要设置随机值?
主要是为了防止锁被其他客户端删除。有这么一种情况:
- 客户端 A 获得了锁,还没有执行结束,但是锁超时自动释放了;
- 客户端 B 此时过来,是可以获得锁的,加锁成功;
- 此时,客户端 A 执行结束了,要去释放锁,如果不对比随机值,就会把客户端 B 的锁给释放了。
当然前面看过 Redisson 的处理,这个 my_random_value 存放的是 UUID:ThreadId 组合成的一个类似 931573de-903e-42fd-baa7-428ebb7eda80:1 的字符串。
。
为什么要用lua脚本操作redis数据库?
1.减少开销–减少向redis服务器的请求次数
2.原子操作–redis将lua脚本作为一个原子执行
3.可复用–其他客户端可以使用已经执行过的lua脚本
4.增加redis灵活性–lua脚本可以帮助redis做更多的事情
相关文章:

分布式锁-Redis红锁解决方案
一 分布式锁的概念 1:概念 分布式锁(多服务共享锁) 在分布式的部署环境下,通过锁机制来让多客户端互斥的对共享资源进行访问控制分布式系统不同进程共同访问共享资源的一种锁的实现。如果不同的系统或同一个系统的不同主机之间共…...

【Ubuntu 终端终结者Ctrl shift e无法垂直分页解决办法】
Ubuntu 终端终结者Ctrl shift e无法垂直分页解决办法 错误原因解决办法 错误原因 这是因为ibus输入法有一个快捷键占用了这个终端终结者的快捷键 解决办法 打开命令行输入 ibus-setup进入到如下页面随后将其中的表情注释的快捷键删除即可...

Error: error:0308010C:digital envelope routines::unsupported
Error: error:0308010C:digital envelope routines::unsupported 问题描述: 使用 npm run dev 或者 yarn run dev 时 报错:Error: error:0308010C:digital envelope routines::unsupported PS D:\Project\dlspeed_all\GS-IMS\ruoyi-ui> npm run de…...

RTMP在智能眼镜行业应用方案有哪些?
方案示例 视频直播:智能眼镜通常具有摄像头和显示屏,可以实时拍摄和显示视频。RTMP协议可以用于将智能眼镜拍摄的视频传输到服务器,以便其他用户可以实时观看。远程协作:智能眼镜可以用于远程协作,例如在医疗、建筑等…...

【每日一题】合并两个有序数组
链接奉上:合并两个有序数组 目录 直接合并后排序:思路:代码实现: 双指针思路:代码实现: 直接合并后排序: 思路: 将nums2直接合并到nums1后边,并进行排序 代码实现&…...

MySQL---表的增查改删(CRUD进阶)
文章目录 数据库约束表的设计一对一一对多多对多 新增查询聚合查询分组查询联合查询内连接外连接自连接子查询合并查询 数据库约束 数据库约束就是指:程序员定义一些规则对数据库中的数据进行限制。这样数据库会在新增和修改数据的时候按照这些限制,对数…...

《HelloGitHub》第 91 期
兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等,涵盖多种编程语言 Python、…...

jvm线上异常排查流程
1. Linux命令 jps 找出当前运行实例 2. jinfo -flags pid(java运行id) 打印出当前设置的jvm内存参数情况 3.jstat -gcutil pid 1000 10 每秒打印一次当前jvm的gc运行情况,一共打印10次 4.将gc日志下载进行分析:到底是因为什么原因导致一直…...

python项目之酒店客房入侵检测系统的设计与实现
项目简介 酒店客房入侵检测系统的设计与实现实现了以下功能: 1、控制台: 控制台是整个系统的首页面。在控制台中,酒店的客房管理人员能够在该页面中查看到当前的空余客房数量、当前在店的客房人数、当前的已用客房数量、当前酒店全部的客房…...

C++ 学习系列 -- 标准库常用得 algorithm function
一 前言 c 标准库中提供了许多操作数据结构:vector、list、deque、map、set 等函数,学习并了解这些常用函数对于我们理解 c 的一些设计模式有着重要的作用。 二 常用的 algorithm function 源码 源代码位置: bits/stl_algo.h 1. accumu…...

[论文笔记]E5
引言 今天又带来一篇文本匹配/文本嵌入的笔记:Text Embeddings by Weakly-Supervised Contrastive Pre-training。中文题目是 基于弱监督对比预训练计算文本嵌入。 本篇工作提出了E5模型(EmbEddings from bidirEctional Encoder rEpresentations)。该模型以带弱监督信号的对…...

k8s 1.28版本:使用StorageClass动态创建PV,SelfLink 问题修复
k8s中提供了一套自动创建 PV 的机制,就是基于 StorageClass 进行的,通过 StorageClass 可以实现仅仅配置 PVC,然后交由 StorageClass 根据 PVC 的需求动态创建 PV。 问题: 使用 k8s 1.28版本,通过 kubectl get pv…...

漏洞复现-dedecms文件上传(CVE-2019-8933)
dedecms文件上传_CVE-2019-8933 漏洞信息 Desdev DedeCMS 5.7SP2版本中存在安全漏洞CVE-2019-8933文件上传漏洞 描述 Desdev DedeCMS(织梦内容管理系统)是中国卓卓网络(Desdev)公司的一套基于PHP的开源内容管理系统&#x…...

vue分片上传
<template><div><input type"file" id"input" /><button click"uploadFile">上传</button></div> </template><script lang"ts" setup> let chunkSize1024 * 1024,index0; const upl…...

【大数据Hive】hive 表数据优化使用详解
目录 一、前言 二、hive 常用数据存储格式 2.1 文件格式-TextFile 2.1.1 操作演示 2.2 文件格式 - SequenceFile 2.2.1 操作演示 2.3 文件格式 -Parquet 2.3.1 Parquet简介 2.3.2 操作演示 2.4 文件格式-ORC 2.4.1 ORC介绍 2.4.2 操作演示 三、hive 存储数据压缩优…...

京东平台数据分析(京东销量):2023年9月京东吸尘器行业品牌销售排行榜
鲸参谋监测的京东平台9月份吸尘器市场销售数据已出炉! 根据鲸参谋电商数据分析平台的相关数据显示,今年9月,京东吸尘器的销量为19万,环比下滑约12%,同比下滑约25%;销售额为1.2亿,环比下滑约11%&…...

基于springboot实现休闲娱乐代理售票平台系统项目【项目源码+论文说明】计算机毕业设计
基于springboot实现休闲娱乐代理售票平台系统演示 摘要 网络的广泛应用给生活带来了十分的便利。所以把休闲娱乐代理售票管理与现在网络相结合,利用java技术建设休闲娱乐代理售票系统,实现休闲娱乐代理售票的信息化。则对于进一步提高休闲娱乐代理售票管…...

jvm对象内存划分
写此篇博客源于面试问到内存分配的细节,然后不明白问的是什么。回过头发现以前看过这块内容,只是有些印象,但是无法描述清楚。 额外概念了解 jvm内存空间是逻辑上连续的虚拟地址空间(虚拟内存中的概念)映射到物理内存…...

网络原理之TCP/IP
文章目录 应用层传输层UDP协议TCP协议TCP 的工作机制1. 确认应答2. 超时重传3. 连接管理TCP 的建立连接的过程(三次握手),和断开连接的过程(四次挥手)TCP 断开连接, 四次挥手 3. 滑动窗口5. 流量控制6. 拥塞控制7. 延时应答8. 捎带应答9. 面向字节流10. 异常情况 本章节主要讨论…...

Docker:数据卷挂载
Docker:数据卷挂载 1. 数据卷2. 数据卷命令补充 1. 数据卷 数据卷(volume)是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁。 Nginx容器有自己独立的目录(Docker为每个镜像创建一个独立的容器,每个容器都是基于镜像创建的运行实例),…...

你会处理 go 中的 nil 吗
对于下面这段代码,我们知道 i 实际上的值就是 nil,所以 i nil 会生效 func main() {var i *int nilif i nil {fmt.Println("i is nil") // i is nil} }现在换一种写法,我们将 i 的类型改成 interface{},i nil 依然…...

高级深入--day42
注意:模拟登陆时,必须保证settings.py里的 COOKIES_ENABLED (Cookies中间件) 处于开启状态 COOKIES_ENABLED True 或 # COOKIES_ENABLED False 策略一:直接POST数据(比如需要登陆的账户信息) 只要是需要提供post数据的ÿ…...

mysql 计算两个坐标距离
方式一:st_distance_sphere 计算结果单位米 SELECT *, st_distance_sphere(point(lng,lat),point(lng,lat)) as distance FROM table mysql 版本5.7 以上 方式二:st_distance 计算结果单位是度 SELECT *, (st_distance(point(lng,lat),point(lng4,lat…...

String、StringBuffer、StringBuilder和StringJoiner
String、StringBuffer、StringBuilder和StringJoiner都是用于处理字符串的类,但它们在性能和使用方式上有一些区别。 String String是不可变的类,一旦创建就不能被修改。对String进行拼接或修改时,实际上是创建了一个新的String对象。适用于…...

【数据结构】插入排序
⭐ 作者:小胡_不糊涂 🌱 作者主页:小胡_不糊涂的个人主页 📀 收录专栏:浅谈数据结构 💖 持续更文,关注博主少走弯路,谢谢大家支持 💖 直接插入、希尔排序 1. 什么是排序2…...

Photoshop使用笔记总目录
Photoshop基础学习之工具学习 一、【Photoshop界面认识】 二、【 Photoshop常用快捷键】 三、【色彩模式与颜色填充】 四、【选区】 五、【视图】 六、【常用工具组】 七、【套索工具组】 八、【快速选择工具组】 九、【裁剪工具组】 十、【图框工具组】 十一、【吸取…...

最近面试遇到的高频面试题
大家好,我是 jonssonyan 互联网寒冬?金九银十真的不存在了么?虽说现在行情是差了一些,面试机会少了一些,但是大部分公司还是或多或少的招人,春招秋招都在进行。有人离职就有人入职。所以如果你还没约到面试…...

负载均衡有哪些算法,分别在nginx中如何配置?
负载均衡是用于分发传入的网络流量到多个后端服务器的技术,以确保无单个服务器过载,从而提高应用的可用性和响应时间。以下是一些常用的负载均衡算法,以及如何在Nginx中配置它们: 轮询 (Round Robin): 简介:…...

Starknet开发工具
1. 引言 目前Starknet的开发工具流可为: 1)Starkli:音为Stark-lie,为替换官方starknet-CLI的快速命令行接口。Starkli为单独的接口,可独自应用,而不是其它工具的组件。若只是想与Starknet交互࿰…...

Unity地面交互效果——1、局部UV采样和混合轨迹
大家好,我是阿赵。 这期开始,打算介绍一下地面交互的一些做法。 比如: Unity引擎制作沙地实时凹陷网格的脚印效果 或者: Unity引擎制作雪地效果 这些效果的实现,需要基于一些基础的知识。所以这一篇先介绍一下简单…...