Redis学习【12】之Redis 缓存
文章目录
- 前言
- 一 Jedis 简介
- 二 使用 Jedis
- 2.1 测试代码
- 2.2 使用 JedisPool
- 2.3 使用 JedisPooled
- 2.4 连接 Sentinel 高可用集群
- 2.5 连接分布式系统
- 2.6 操作事务
- 三 Spring Boot整合Redis
- 3.1 创建工程
- 3.2 定义 pom 文件
- 3.3 完整代码
- 3.4 总结
- 四 高并发问题
- 4.1 缓存穿透
- 4.2 缓存击穿
- 4.3 缓存雪崩
- 4.5 数据库缓存双写不一致
- 4.5.1 “修改 DB 更新缓存”场景
- 4.5.2 “修改 DB 删除缓存”场景
- 4.5.3 解决方案:延迟双删
- 4.5.4 解决方案:队列
- 4.5.4 解决方案:分布式锁
前言
- 本文是作者在学习redis的笔记,学习动力节点的redis课程
- 仅供学习交流,不得用于商业用途
一 Jedis 简介
- Jedis 是一个基于 java 的 Redis 客户端连接工具,旨在提升性能与易用性。github 上的官网地址
二 使用 Jedis
- Jedis 基本使用十分简单,其提供了非常丰富的操作 Redis 的方法,而这些方法名几乎与Redis 命令相同。
- 在每次使用时直接创建 Jedis 实例即可。在 Jedis 实例创建好之后,Jedis 底层实际会创建一个到指定 Redis 服务器的 Socket 连接。所以,为了节省系统资源与网络带宽,在每次使用完 Jedis 实例之后,需要立即调用 close()方法将连接关闭。
- 首先创建一个普通的 Maven 工程 ,然后在 POM 文件中添加 Jedis 与 Junit 依赖
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.2.0</version>
</dependency>
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version>
</dependency>
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version>1.7.25</version><scope>test</scope>
</dependency>
2.1 测试代码
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.resps.Tuple;import java.util.HashMap;
import java.util.List;
import java.util.Set;/*** @author 缘友一世* date 2023/3/8-22:44*/
public class test {/*** value 为 String 的测试*/@Testpublic void test01() {Jedis jedis = new Jedis("192.168.28.123", 6379);jedis.set("name","007");jedis.mset("age","23","depart","market");System.out.println(jedis.get("name"));System.out.println(jedis.get("age"));System.out.println(jedis.get("depart"));jedis.close();}/*** value 为 Hash 的测试*/@Testpublic void test02() {Jedis jedis = new Jedis("192.168.28.123", 6379);jedis.hset("direction","east","north");HashMap<String, String> map = new HashMap<>();map.put("height","500m");map.put("character","major");jedis.hset("mapTest",map);String heigt = jedis.hget("mapTest", "height");List<String> mapTest = jedis.hmget("mapTest", "height", "character");System.out.println("height:"+heigt);System.out.println("mapTest:"+mapTest);jedis.close();}/*** value 为 List 的测试*/@Testpublic void test03() {Jedis jedis = new Jedis("192.168.28.123", 6379);jedis.rpush("cities","冰雪北境","南幻水乡","西凉荒漠");List<String> cities = jedis.lrange("cities", 0, -1);System.out.println("cities:"+cities);jedis.close();}/*** value 为 Set 的测试*/@Testpublic void test04() {Jedis jedis = new Jedis("192.168.28.123", 6379);long sadd = jedis.sadd("midwares", "Redi", "Nginx", "RocketMQ");Set<String> midwares = jedis.smembers("midwares");System.out.println("midwares:"+midwares);jedis.close();}/*** value 为 zSet 的测试*/@Testpublic void test05() {Jedis jedis = new Jedis("192.168.28.123", 6379);jedis.zadd("sales",80,"BMW");jedis.zadd("sales",90,"BYD");jedis.zadd("sales",60,"Benz");jedis.zadd("sales",70,"BMW");//获取销量前三List<String> top = jedis.zrevrange("sales", 0, 2);System.out.println("top:"+top);List<Tuple> sales = jedis.zrevrangeWithScores("sales", 0, -1);for (Tuple sale:sales) {System.out.println(sale.getScore()+":"+sale.getElement());}jedis.close();}
}
2.2 使用 JedisPool
- 如果应用非常频繁地创建和销毁 Jedis 实例,虽然节省了系统资源与网络带宽,但会大大降低系统性能。因为创建和销毁 Socket 连接是比较耗时的。此时可以使用 Jedis 连接池来解决该问题。
- 使用 JedisPool 与使用 Jedis 实例的区别是,JedisPool 是全局性的,整个类只需创建一次即可,然后每次需要操作 Redis 时,只需从 JedisPool 中拿出一个 Jedis 实例直接使用即可。使用完毕后,无需释放 Jedis 实例,只需返回 JedisPool 即可。
/*** @author 缘友一世* date 2023/3/8-23:12*/
public class jedisPool {@Testpublic void test01(){JedisPool jedisPool = new JedisPool("192.168.28.123", 6379);try(Jedis jedis=jedisPool.getResource()) {jedis.set("name","007");jedis.mset("age","23","depart","market");System.out.println("name:"+jedis.get("name"));System.out.println("age"+jedis.get("age"));System.out.println("depart"+jedis.get("depart"));}}
}
2.3 使用 JedisPooled
- 对于每次对 Redis 的操作都需要使用 try-with-resource 块是比较麻烦的,而使用
JedisPooled
则无需再使用该结构来自动释放资源
/*** 使用JedisPooled 则无需再使用该结构来自动释放资源*/
@Test
public void test02(){JedisPooled jedisPooled = new JedisPooled("192.168.28.123", 6379);//value为string的情况jedisPooled.set("id","212666");jedisPooled.mset("tools","weChat","search","everything");System.out.println("id:"+jedisPooled.get("id"));System.out.println("tools:"+jedisPooled.get("tools"));System.out.println("search:"+jedisPooled.get("search"));
}
2.4 连接 Sentinel 高可用集群
- 对于 Sentinel 高可用集群的连接,直接使用 JedisSentinelPool 即可。在该客户端只需注册所有 Sentinel 节点及其监控的 Master 的名称即可,无需出现 master-slave 的任何地址信息。
- 其采用的也是 JedisPool,使用完毕的 Jedis 也需要通过 close()方法将其返回给连接池。
/*** @author 缘友一世* date 2023/3/9-9:20*/
public class jedisSentinelPoolTest {private JedisSentinelPool jedisPool;{Set<String> sentinels = new HashSet<>();sentinels.add("192.168.28.123:26380");sentinels.add("192.168.28.123:26381");sentinels.add("192.168.28.123:26382");jedisPool = new JedisSentinelPool("mymaster", sentinels);}@Testpublic void test01(){try(Jedis jedis=jedisPool.getResource()) {jedis.set("math","100");jedis.mset("math2","100","age2","18");System.out.println("math:"+jedis.get("math"));System.out.println("math2:"+jedis.get("math2"));System.out.println("age2:"+jedis.get("age2"));}}@Testpublic void test() {Jedis jedis = new Jedis("192.168.28.123", 6380);System.out.println(jedis.get("name"));}
}
2.5 连接分布式系统
- 对于 Redis 的分布式系统的连接,直接使用 JedisCluster 即可。其底层采用的也是 Jedis连接池技术。每次使用完毕后,无需显式关闭,其会自动关闭。
- 对于 JedisCluster 常用的构造器有两个:
- 一个是只需一个集群节点的构造器,这个节点可以是集群中的任意节点,只要连接上了该节点,就连接上了整个集群。但该构造器存在一个风险:其指定的这个节点在连接之前恰好宕机,那么该客户端将无法连接上集群。
- 所以,推荐使用第二个构造器,即将集群中所有节点全部罗列出来。这样就会避免这种风险
/*** @author 缘友一世* date 2023/3/9-12:29*/
public class jedisClusterTest {private JedisCluster jedisCluster;{HashSet<HostAndPort> nodes = new HashSet<>();nodes.add(new HostAndPort("192.168.28.123",6380));nodes.add(new HostAndPort("192.168.28.123",6381));nodes.add(new HostAndPort("192.168.28.123",6382));nodes.add(new HostAndPort("192.168.28.123",6383));nodes.add(new HostAndPort("192.168.28.123",6384));nodes.add(new HostAndPort("192.168.28.123",6385));jedisCluster=new JedisCluster(nodes);}@Testpublic void test01(){jedisCluster.set("name","wuwang");System.out.println("name:"+jedisCluster.get("name"));}
}
2.6 操作事务
- 对于 Redis 事务的操作,Jedis 提供了 multi()、watch()、unwatch()方法来对应 Redis 中的multi、watch、unwatch 命令。Jedis的 multi()方法返回一个 Transaction 对象,其 exec()与 discard()方法用于执行和取消事务的执行
/*** @author 缘友一世* date 2023/3/9-23:04*/
public class jedisTxTest {public static void main(String[] args) {JedisPool jedisPool = new JedisPool("192.168.28.123", 6379);try(Jedis jedis=jedisPool.getResource()) {jedis.set("name","001");//构造异常Transaction multi = jedis.multi();try {int i=1/0;multi.set("name","002");multi.exec();}catch (Exception e) {//发生异常全部,回滚multi.discard();}finally {System.out.println(jedis.get("name"));}}}
}
三 Spring Boot整合Redis
- 下面通过一个例子来说明 Spring Boot 是如何与 Redis 进行整合的。
- 对于一个资深成熟的金融产品交易平台,其用户端首页一般会展示其最新金融产品列表,同时还为用户提供了产品查询功能。另外,为了显示平台的实力与信誉,在平台首页非常显眼的位置还会展示平台已完成的总交易额与注册用户数量。对于管理端,管理员可通过管理
页面修改产品、上架新产品、下架老产品。 - 为了方便了解 Redis 与 Spring Boot 的整合流程,这里对系统进行了简化:用户端首页仅提供根据金融产品名称的查询,显眼位置仅展示交易总额。管理端仅实现上架新产品功能。
- 对于一个资深成熟的金融产品交易平台,其用户端首页一般会展示其最新金融产品列表,同时还为用户提供了产品查询功能。另外,为了显示平台的实力与信誉,在平台首页非常显眼的位置还会展示平台已完成的总交易额与注册用户数量。对于管理端,管理员可通过管理
3.1 创建工程
- 定义一个 Spring Boot 工程
3.2 定义 pom 文件
- 在 pom 文件中需要导入 MySQL 驱动、Druid 等大量依赖
DROP TABLE IF EXISTS `product`;
CREATE TABLE `product` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(20) DEFAULT NULL,`rate` double DEFAULT NULL,`amount` double DEFAULT NULL,`raised` double DEFAULT NULL,`cycle` int(11) DEFAULT NULL,`endTime` char(10) DEFAULT '0',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;INSERT INTO `product` VALUES
(1,'天鑫添益 2',2.76,50000,20000,30,'2022-07-10'),
(2,'国泰添益',2.86,30000,30000,60,'2022-07-12'),
(3,'国泰高鑫',2.55,60000,50000,90,'2022-07-09'),
(4,'国福民安',2.96,30000,20000,7,'2022-05-10'),
(5,'天益鑫多',2.65,80000,60000,20,'2022-07-05'),
(6,'惠农收益',3.05,30000,20000,10,'2022-06-10'),
(7,'惠农三鑫',2.76,50000,30000,30,'2022-07-02'),
(8,'励学收益',2.86,30000,20000,20,'2022-07-11');
3.3 完整代码
- 项目源码地址
- 源码的内容,自动力节点案例的改进【主要解决:打开主页面,直接卸载jsp文件的错误】
- 这里作者遇到了打开jsp主页,直接下载了jsp文件。可能的原因是浏览器配置了
NDM
多线程下载器
3.4 总结
- 如何将 Spring Boot 与 Redis 整合?
- 在 POM 中导入依赖
- 在配置文件中注册 Redis 连接信息与缓存信息
- 需要缓存到 Redis 中的实体类必须要序列化
- Spring Boot 启动类中要添加@EnableCaching 注解
- 查询方法上要添加@Cacheable 注解
- 对数据进行写操作的方法上添加@CacheEvict 注解
- 对于需要手工操作 Redis 的方法,需通过 RedisTemplate 来获取操作对象
四 高并发问题
- Redis 做缓存虽减轻了 DBMS 的压力,减小了 RT,但在高并发情况下也是可能会出现各种问题的。
4.1 缓存穿透
- 当用户访问的数据既不在缓存也不在数据库中时,就会导致每个用户查询都会“穿透”缓存“直抵”数据库。这种情况就称为缓存穿透。当高度发的访问请求到达时,缓存穿透不仅增加了响应时间,而且还会引发对 DBMS 的高并发查询,这种高并发查询很可能会导致DBMS 的崩溃。
- 缓存穿透产生的主要原因有两个:一是在数据库中没有相应的查询结果,二是查询结果为空时,不对查询结果进行缓存。所以,针对以上两点,解决方案也有两个:
- 对非法请求进行限制
- 对结果为空的查询给出默认值
4.2 缓存击穿
- 对于某一个缓存,在高并发情况下若其访问量特别巨大,当该缓存的有效时限到达时,可能会出现大量的访问都要重建该缓存,即这些访问请求发现缓存中没有该数据,则立即到DBMS 中进行查询,那么这就有可能会引发对 DBMS 的高并发查询,从而接导致 DBMS 的崩溃。这种情况称为缓存击穿,而该缓存数据称为热点数据。
- 对于缓存击穿的解决方案,较典型的是使用“双重检测锁”机制。
4.3 缓存雪崩
- 对于缓存中的数据,很多都是有过期时间的。若大量缓存的过期时间在同一很短的时间段内几乎同时到达,那么在高并发访问场景下就可能会引发对 DBMS 的高并发查询,而这将可能直接导致 DBMS 的崩溃。这种情况称为缓存雪崩。
- 对于缓存雪崩没有很直接的解决方案,最好的解决方案就是预防,即提前规划好缓存的过期时间。要么就是让缓存永久有效,当 DB 中数据发生变化时清除相应的缓存。如果 DBMS采用的是分布式部署,则将热点数据均匀分布在不同数据库节点中,将可能到来的访问负载
均衡开来。
4.5 数据库缓存双写不一致
- 以上三种情况都是针对高并发读场景中可能会出现的问题,而数据库缓存双写不一致问题,则是在高并发写场景下可能会出现的问题。
对于数据库缓存双写不一致问题,以下两种场景下均有可能会发生:
4.5.1 “修改 DB 更新缓存”场景
- 对于具有缓存 warmup 功能的系统,DBMS 中常用数据的变更,都会引发缓存中相关数据的更新。在高并发写请求场景下,若多个请求要对 DBMS 中同一个数据进行修改,修改后还需要更新缓存中相关数据,那么就有可能会出现缓存与数据库中数据不一致的情况。
4.5.2 “修改 DB 删除缓存”场景
- 在很多系统中是没有缓存 warmup 功能的,为了保持缓存与数据库数据的一致性,一般都是在对数据库执行了写操作后,就会删除相应缓存。
- 在高并发读写请求场景下,若这些请求对 DBMS 中同一个数据的操作既包含写也包含读,且修改后还要删除缓存中相关数据,那么就有可能会出现缓存与数据库中数据不一致的情况
4.5.3 解决方案:延迟双删
- 延迟双删方案是专门针对于“修改 DB 删除缓存”场景的解决方案。但该方案并不能彻底解决数据不一致的状况,其只可能降低发生数据不一致的概率。
- 延迟双删方案是指,在写操作完毕后会立即执行一次缓存的删除操作,然后再停上一段时间(一般为几秒)后再进行一次删除。而两次删除中间的间隔时长,要大于一次缓存写操作的时长。
4.5.4 解决方案:队列
- 以上两种场景中,只所以会出现数据库与缓存中数据不一致,主要是因为对请求的处理出现了并行。只要将请求写入到一个统一的队列,只有处理完一个请求后才可处理下一个请求,即使系统对用户请求的处理串行化,就可以完全解决数据不一致的问题。
4.5.4 解决方案:分布式锁
- 使用队列的串行化虽然可以解决数据库与缓存中数据不一致,但系统失去了并发性,降低了性能。使用分布式锁可以在不影响并发性的前提下,协调各处理线程间的关系,使数据库与缓存中的数据达成一致性。
- 只需要对数据库中的这个共享数据的访问通过分布式锁来协调对其的操作访问即可。
相关文章:
Redis学习【12】之Redis 缓存
文章目录前言一 Jedis 简介二 使用 Jedis2.1 测试代码2.2 使用 JedisPool2.3 使用 JedisPooled2.4 连接 Sentinel 高可用集群2.5 连接分布式系统2.6 操作事务三 Spring Boot整合Redis3.1 创建工程3.2 定义 pom 文件3.3 完整代码3.4 总结四 高并发问题4.1 缓存穿透4.2 缓存击穿4…...
Bootargs 参数
bootargs 的参数有很多,而且随着 kernel 的发展会出现一些新的参数,使得设置会更加灵活多样1。除了我之前介绍的 root、console、earlyprintk 和 loglevel 之外,还有以下一些常用的参数:init: 用来指定内核启动后执行的第一个程序…...
Mybatis框架源码笔记(七)之Mybatis中类型转换模块(TypeHandler)解析
1、JDBC的基本操作回顾 这里使用伪代码概括一下流程: 对应数据库版本的驱动包自行下载加载驱动类 (Class.forName("com.mysql.cj.jdbc.Driver"))创建Connection连接: conn DriverManager.getConnection("jdbc:mysql://数据库IP:port/数据库名称?useUnico…...
论文阅读《Block-NeRF: Scalable Large Scene Neural View Synthesis》
论文地址:https://arxiv.org/pdf/2202.05263.pdf 复现源码:https://github.com/dvlab-research/BlockNeRFPytorch 概述 Block-NeRF是一种能够表示大规模环境的神经辐射场(Neural Radiance Fields)的变体,将 NeRF 扩展到…...
【Matlab】如何设置多个y轴
MTALAB提供了创建具有两个y轴的图,通过help yyaxis就能看到详细的使用方式。 但是如果要实现3个及以上y轴的图,就没有现成的公式使用了,如下图所示。 具体代码 % 数据准备 x10:0.01:10; y1sin(x1); x20:0.01:10; y2cos(x2); x30:0.01:10;…...
圆桌(满足客人空座需求,合理安排客人入座圆桌,准备最少的椅子)
CSDN周赛第30期第四题算法解析。 (本文获得CSDN质量评分【91】)【学习的细节是欢悦的历程】Python 官网:https://www.python.org/ Free:大咖免费“圣经”教程《 python 完全自学教程》,不仅仅是基础那么简单…… 地址:https://lq…...
如何入门大数据?
我们首先了解一下大数据到底是什么~ 大数据开发做什么? 大数据开发分两类,编写Hadoop、Spark的应用程序和对大数据处理系统本身进行开发。 大数据开发工程师主要负责公司大数据平台的开发和维护、相关工具平台的架构设计与产品开发、网络日志大数据分…...
如何在Vite项目中使用Lint保证代码质量
通常,大型前端项目都是多人参与的,由于开发者的编码习惯和喜好都不尽相同,为了降低维护成本,提高代码质量,所以需要专门的工具来进行约束,并且可以配合一些自动化工具进行检查,这种专门的工具称为Lint,可能大家接触得最多就是ESLint。 对于实现自动化代码规范检查及修…...
Spark高手之路1—Spark简介
文章目录Spark 概述1. Spark 是什么2. Spark与Hadoop比较2.1 从时间节点上来看2.2 从功能上来看3. Spark Or Hadoop4. Spark4.1 速度快4.2 易用4.3 通用4.4 兼容5. Spark 核心模块5.1 Spark-Core 和 弹性分布式数据集(RDDs)5.2 Spark SQL5.3 Spark Streaming5.4 Spark MLlib5.5…...
社科院与杜兰大学金融管理硕士项目——人生没有太晚的开始,不要过早的放弃
经常听到有人问,“我都快40了,现在学车晚不晚呢”“现在考研晚不晚?”“学画画晚不晚?”提出这些疑问的人,往往存在拖延,想法只停留在想的阶段,从来不去行动。当看到周边行动起来的人开始享受成…...
Spatial-Temporal Graph ODE Networks for Traffic Flow Forecasting
Spatial-Temporal Graph ODE Networks for Traffic Flow Forecasting 摘要 交通流量的复杂性和长范围时空相关性是难点 经典现存的工作: 1.利用浅图神经网络(shallow graph convolution networks)和 时间提取模块去分别建模空间和时间依赖…...
IP协议+以太网协议
在计算机网络体系结构的五层协议中,第三层就是负责建立网络连接,同时为上层提供服务的一层,网络层协议主要负责两件事:即地址管理和路由选择,下面就网络层的重点协议做简单介绍~~ IP协议 网际协议IP是TCP/IP体系中两…...
可视化组件届的仙女‖蝴蝶结图、玫瑰环图、小提琴图
在上一篇内容中为大家介绍了几个堪称可视化组件届吴彦祖的高级可视化图表。既然帅哥有了,怎么能少得了美女呢?今天就为大家介绍几个可视化组件届的“美女姐姐”,说一句是组件届的刘亦菲不为过。蝴蝶结图蝴蝶结图因其形似蝴蝶结而得名…...
人的高级认知:位置感
你知道吗?人有个高级认知:位置感 位置感是啥?咋提高位置感? 趣讲大白话:知道自己几斤几两 【趣讲信息科技99期】 ******************************* 位置感 就是对自己所处环境和自身存在的领悟 属于人生智慧 来源于阅历…...
MATLAB——信号的采样与恢复
**题目:**已知一个连续时间信号 其中:f01HZ,取最高有限带宽频率fm5f0。分别显示原连续时间信号波形和 3种情况下抽样信号的波形。并画出它们的幅频特性曲线,并对采样后的信号进行恢复。 step1.绘制出采样信号 这部分相对简单…...
Docker Nginx 反向代理
最近在系统性梳理网关的知识,其中网关的的功能有一个是代理,正好咱们常用的Nginx也具备次功能,今天正好使用Nginx实现一下反向代理,与后面网关的代理做一个对比,因为我使用的docker安装的Nginx,与直接部署N…...
手把手教你实现书上的队列,进来试试?
一.队列的基本概念队列的定义队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。队列是一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一端称为队尾,允…...
【springboot】springboot介绍
学习资料 SpringBoot 语雀 (yuque.com)【尚硅谷】SpringBoot2零基础入门教程(spring boot2干货满满)_哔哩哔哩_bilibiliSpringBoot2核心技术与响应式编程: SpringBoot2核心技术与响应式编程 (gitee.com) Spring 和Springboot 1、Spring能做什么 1.1…...
PMP项目管理项目整合管理
目录1 项目整合管理概述2 制定项目章程3 制定项目管理计划4 指导与管理项目工作5 管理项目知识6 监控项目工作7 实施整体变更控制8 结束项目或阶段1 项目整合管理概述 项目整合管理包括对隶属于项目管理过程组的各种过程和项目管理活动进行识别、定义、组合、统一和协调的各个…...
ADS中导入SPICE模型
这里写目录标题在官网中下载SPICE模型ADS中导入SPICE模型在官网中下载SPICE模型 英飞凌官网 ADS中导入SPICE模型 点击option,设置导入选项 然后点击ok 如果destination选择当前的workspace,那么导入完成之后如下: (推荐使用…...
C++:异常
在学习异常之前,来简单总结一下传统的处理错误的方式: 1. 终止程序,如assert,缺陷:用户难以接受。如发生内存错误,除0错误时就会终止程序。 2. 返回错误码,缺陷:需要程序员自己去查找…...
3.初识Vue
目录 1 vue 浏览器调试工具 1.1 安装 1.2 配置 2 数据驱动视图与双向数据绑定 3 简单使用 3.1 下载 3.2 将信息渲染到DOM上 4 使用vue浏览器调试工具 5 vue指令 1 vue 浏览器调试工具 chrome可能是我浏览器的原因,装上用不了,我们使…...
【C语言复习】程序的编译与链接
程序的编译与链接写在前面程序的编译与链接编译的过程程序编译环境程序执行过程编译链接的过程预处理预处理符号#define条件编译写在前面 程序的编译与链接是C语言中非常重要的一节。关键点在于详解C语言的程序编译和链接、宏的定义和与函数的区别、条件编译等知识。 程序的编…...
Golang sql 事务如何进行分层
在写代码过程中遇到了需要使用gorm执行sql事务的情况,研究了一下各位大佬的实现方案,结合了自身遇到的问题,特此记录。 代码架构介绍 . ├── apis ├── config ├── internal │ ├── constant │ ├── controller │ ├──…...
linux系统openssh升级
linux系统openssh升级 说明 整个过程不需要卸载原先的openssl包和openssh的rpm包。本文的环境都是系统自带的openssh,没有经历过手动编译安装方式。如果之前有手动编译安装过openssh,请参照本文自行测试是否能成功。 如果严格参照本文操作,保…...
力扣-求关注者的数量
大家好,我是空空star,本篇带大家了解一道简单的力扣sql练习题。 文章目录前言一、题目:1729. 求关注者的数量二、解题1.正确示范①提交SQL运行结果2.正确示范②提交SQL运行结果3.正确示范③提交SQL运行结果4.正确示范④提交SQL运行结果5.正确…...
近红外荧光染料修饰氨基IR 825 NH2,IR 825-Amine,IR-825 NH2
IR 825 NH2,IR 825-NH2,IR825 Amine,IR825-Amine,新吲哚菁绿-氨基,荧光染料修饰氨基产品规格:1.CAS号:N/A2.包装规格:10mg,25mg,50mg,包装灵活&am…...
Android Crash和ANR监控
文章目录一、Crash1.1 概念1.2 类型二、ANR2.1 概念2.2 类型2.2.1 KeyDispatchTimeout(常见)2.2.2 BroadcastTimeout2.2.3 ServiceTimeout2.2.4 ContentProviderTimeout三、测试中如何关注3.1 Crash测试关注方法3.2 ANR测试关注方法四、如何记录与处理4.…...
【02 赖世雄英语语法:复句的语法】
复句的语法复句:把单句 连在一起(标点符号,连词,关系词)1. 连接符号1.1 破折号 — :补充说明,同位语1.2 冒号 : (同位语)1.3 分号 ; ( , 连词)&am…...
北斗导航 | 多参考一致性监测算法(MRCC)(附伪码)—— B值计算
===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== MRCC 用于接收机失效检查与排除。在进行 MRCC 之前,先判断 4 台接收机…...
柳州免费做网站的公司/百度推广
参考博客: 链接: Android软著申请总结...
wordpress 添加搜索栏/今日军事新闻头条视频
构造方法:实现在实例化之后为属性赋值; 构造方法是类的一个特殊成员,在类实例化后被自动调用。 (一)构造方法的定义 一,构造方法满足以下三个条件: 方法名与类名相同;在方法名前没有…...
台湾网站建设/seo是哪个英文的缩写
一,问题描述 MSVCRTD.lib(crtexew.obj) : error LNK2019: 无法解析的外部符号 _WinMain16,该符号在函数 ___tmainCRTStartup 中被引用 Debug\jk.exe : fatal error LNK1120: 1 个无法解析的外部命令 error LNK2001: unresolved external symbol _WinMai…...
陕西电信网站备案信息真实性核验委托书/企业网络营销青岛
概念介绍1、onInterceptTouchEvent()是用于处理事件(重点onInterceptTouchEvent这个事件是从父控件开始往子控件传的,直到有拦截或者到没有这个事件的view,然后就往回从子到父控件,这次是onTouch的)(类似于…...
html中文网页模板素材/seo网站推广怎么做
1. 第十周之前交作业 2. http://ispacs07.hqu.edu.cn/temp/upu/angel.php 3. 作业要求: a. 源代码 b. apk c. 实验报告(帮别人测试的写入) 测试: 1. 装mantis 2. 报告上写明帮别人测试,涉及的测试用例,我…...
怎么建设和聚享游一样的网站呢/seog
http://blog.csdn.net/ahalei/article/details/20533559...