MongoDB入门(特点,使用场景,命令行操作,SpringData-MongoDB)

news2024/11/28 19:28:17

今天我们将通过这一篇博客来了解MongoDB的体系结构,命令行操作和在JAVA 当中使用SpringData-MongoDB 来 操作MongoDB。

如果没有安装的小伙伴 可以看一下 这篇文章 (59条消息) 开源的文档型数据库–MongoDB(安装)_一切总会归于平淡的博客-CSDN博客,将MongoDB安装一下。

我们来看看MongoDB 的数据特征:

  1. 数据存储量较大,甚至是海量
  2. 对数据读写的响应速度较高
  3. 数据安全性不高,有一定范围内的误差

看到这里,有的小伙伴可能就会问?哎呀,我去,这个MongoDB 这么牛的吗?

那它为什么这么牛?我们就要看看它的特点。

1、特点

1.1 数据存储

MongoDB的第一个特点:数据存储

MongoDB是借助 内存 + 磁盘 共同 来完成数据存储的,那客户端和MongoDB进行交互有分成了两个部分。

image-20230112145419358

客户端的操作,首先操作的是内存,那我们知道,内存的操作速度和操作磁盘的速度的是吧,那走内存肯定是比走磁盘的速度要快很多的。

所以说,如果你的内存足够大的话,我要想从mengoDB查询,直接就能从内存来进行查询,就避免了走磁盘查询。

当然,如果内存没有的话,它还会从磁盘当中来进行读取,接着返回给客户端。

上面说的是查询,写入也是先写入到内存当中,那接着就返回给客户端,所以要进行写入的话,其实直接操作的就是内存,那它的效率就嘎嘎的高。

那大家可能就会有疑问了,现在数据在内存当中,那我这个服务器重启,数据岂不是都消失了?

这一点,MongoDB会借助操作系统的机制,它会把内存中的数据自动映射到磁盘,只不过,它会有一个时间的规则,每60秒会写入一次。

这有没有问题呢?

那肯定是有的,如果说内存当中,已经写入了数据,还没有同步到磁盘上去,这个断电了,那是不是意味着刚刚这60秒的数据就丢失了,这也就解释了为什么MongDB它的效率比较高,因为它操作的是内存。

然后就是MongoDB为什么会有数据丢失的问题呢?因为它涉及到了内存和磁盘的数据同步。

为了解决这个问题,MongoDB在后面的版本当中,对结构进行了优化。image-20230112150656101

它把内存分成两部分,一个是代表日志,一个是真正的业务数据,同样的磁盘也分成了两块,一个是日志文件,一个是业务数据文件。

客户端发送请求到内存当中,首先要把你的操作记录日志,记录好之后写入到业务数据的内存部分,那日志的内存部分会跟磁盘上的日志部分进行10毫秒数据同步。

那业务数据部分,会经过60秒数据同步。

这种设计它有什么好处?首先如果当服务器它再次断电了,由于日志它们进行数据同步的时间比价短,毕竟都从60缩到了10毫秒,所以不间断的吧所有的操作日志都同步到了日志文件上。

虽然业务数据可能会有60时间的丢失,但是没有关系,日志文件会出手,当服务器 重启的时候,它会解析日志文件里面的内容和业务数据的内容,将它俩进行对比。

将丢失的内容太补偿到文件当中进行存储,但是,不管mongoDB再怎么努力,都会有一定时间间隔的数据丢失。

1.2 高扩展性

mongoDB 的搞扩展性是借助内置数据分片来实现的,在我们使用MongoDB的时候,往往会有这种情况,mongDB由于自己的硬盘存储容量有限,导致多余的数据可能就存不下去了。

那这个时候怎么办?借助内置的数据分片,我们可以将多个mongoDB服务器串联到一起,每台机器存储一部分,这样一来,数据存储量就很多了。

使用mongDB的内置数据分片可以很轻松的存下海量的数据内容,这也为海量数据打下基础。虽然MySQL也支持数据分片,只不过需要借助第三方的服务和组件来实现,实现成本可能会高一些。

2、对比

看了上面对mengoDB的特点介绍,大家可能会有一点懵,我嘞个去,redis已经很厉害了,mysql 也很牛,现在又来了一个mongoDB,我该如何选择呢?

  1. 与Redis的对比
    1. Redis纯内存数据库,内存不足触发淘汰策略,那这部分内容就真的丢失了!
    2. 结构化存储格式(Bson),方便扩展。
    3. mongDB可以根据某个字段去查询,而这并不是Redis 擅长的。
  2. 与MySQL对比
    1. MongoDB不支持事务和多表操作; 比如用户的账号需要满足多个操作的同时成功/失败,那用mongDB就不太合适了。
    2. MongoDB支持动态字段管理。 例:数据的字段有两项,你再保存一条 变成了三项,在保存一条四项,字段的个数和字段的类型是灵活变化的,但mysql一旦将字段定义完成,就很难修改。

从查询效率上来进行对比:

Redis -> MongoDB -> MySQL

3、使用场景

  1. 游戏装备数据、游戏道具数据
    1. 特征:修改频度较高
  2. 物流行业数据
    1. 特征:地理位置信息,海量数据
  3. 直播数据、打赏数据、粉丝数据
    1. 特征:数据量大,修改频度极高
  4. 日志数据
    1. 特征:数据量巨大,结构多变

以上就是mengoDB的适用场景吗,如果大家在实际项目中遇到类似的场景,或许可以选择将数据存储到mengoDB当中来。

4、MongoDB的体系结构与术语

MongoDB 是最像关系型数据库的非关系型数据库,之所以这样子说,是因为它的体系结构和MySQL 是比较像的。

我们通过对比的形式对 MongoDB 的体系结构做一个初步的了解。

SQL术语/概念MongoDB术语/概念解释/说明
databasedatabase数据库
tablecollection数据库表/集合
rowdocument表中的一条数据
columnfield数据字段/域
indexindex索引
table joins表连接,MongoDB不支持
primary keyprimary key主键,MongoDB自动将_id字段设置为主键

image-20230117140726215

了解了MongoDB的体系结构我们来看看它的数据结构。

MongoDB中使用Bson存储数据( Binary JSON ),一种类似Json的数据格式。

我们来看看一条数据如何已BSON 的形式显示出来,我呢通过MySQL 对比看看。

MySQL:

image-20230117141046130

MongoDB:

image-20230117141148121

5、MongoDB 命令行操作

了解MongoDB的基本概念之后我们就可以来进行对MongoDB 的入门了。

5.1 数据库以及表的操作

1、查询所有数据库。

show dbs

2、通过use关键字切换数据库。

use 切换的数据库

image-20230117142228141

3、创建数据库 :在MongoDB中,数据库是自动创建的,通过use切换到新数据库中,进行插入数据即可自动创建数据库。

use testdb2

现在查询数据库,并未出现数据库。

image-20230117142703713

插入数据。

db.user.insert({id:1,name:'zhangsan'})

image-20230117142810998

现在查询。

image-20230117143008626

4、查看表。

show tables

image-20230117143142995

show collections

image-20230117143805152

5、删除集合(表)。

db.user.drop()

image-20230117143928068

6、删除数据库 (需要先切换到要删除的数据中)

use 要切换的数据库

删除

db.dropDatabase() 

5.2 新增数据

1、插入数据(语法:db.表名.insert(json字符串))

db.user.insert({id:1,username:'zhangsan',age:20})

2、查询数据

db.user.find()

image-20230117144737976

这里可能大家会有疑问,为什么还有一个下划线id,这是因为MongoDB它自己有一个默认的主键ID,就是这个_id。

5.3 更新数据

update() 方法用于更新已存在的文档。语法格式如下:

db.collection.update(
   <query>,
   <update>,
   [
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>
   ]
)

参数说明:

  • query : update的查询条件,类似sql update查询内where后面的。
  • update : update的对象和一些更新的操作符(如 , , ,inc.$set)等,也可以理解为sql update查询内set后面的
  • upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
  • multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
  • writeConcern :可选,抛出异常的级别。

案例:

db.user.update({id:1},{$set:{age:22}}) 

image-20230117145525202

更新不存在的数据,默认不会新增数据。

db.user.update({id:2},{$set:{sex:1}})

image-20230117150134844

5.4 删除数据

通过remove()方法进行删除数据,语法如下:

db.collection.remove(
   <query>,
   {
     justOne: <boolean>,
     writeConcern: <document>
   }
)

参数说明:

  • query :(可选)删除的文档的条件。
  • justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
  • writeConcern :(可选)抛出异常的级别。

代码演示:

首先我们先插入数据。

db.user.insert({id:1,username:'zhangsan',age:20})
db.user.insert({id:2,username:'lisi',age:21})
db.user.insert({id:3,username:'wangwu',age:22})
db.user.insert({id:4,username:'zhaoliu',age:22})

删除年龄为22 的数据,只删除一个。

db.user.remove({age:22},true)

删除所有数据。

db.user.remove({})

5.5 查询数据

MongoDB 查询数据的语法格式如下:

db.user.find([query],[fields])
  • query :可选,使用查询操作符指定查询条件
  • fields :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。

条件查询:

操作格式范例RDBMS中的类似语句
等于{<key>:<value>}db.col.find({"by":"一切总会归于平淡"}).pretty()where by = '一切总会归于平淡'
小于{<key>:{$lt:<value>}}db.col.find({"likes":{$lt:50}}).pretty()where likes < 50
小于或等于{<key>:{$lte:<value>}}db.col.find({"likes":{$lte:50}}).pretty()where likes <= 50
大于{<key>:{$gt:<value>}}db.col.find({"likes":{$gt:50}}).pretty()where likes > 50
大于或等于{<key>:{$gte:<value>}}db.col.find({"likes":{$gte:50}}).pretty()where likes >= 50
不等于{<key>:{$ne:<value>}}db.col.find({"likes":{$ne:50}}).pretty()where likes != 50

代码演示:

插入数据:

db.user.insert({id:1,username:'zhangsan',age:20})
db.user.insert({id:2,username:'lisi',age:21})
db.user.insert({id:3,username:'wangwu',age:22})
db.user.insert({id:4,username:'zhaoliu',age:22})

1、查询全部数据:

db.user.find() 

image-20230126140911445

2、只查询id与username字段。

db.user.find({},{id:1,username:1})

image-20230126141024948

3、查询数据条数

db.user.find().count()

image-20230126141125038

4、查询id为1的数据

db.user.find({id:1})

image-20230126141153811

5、查询age小于等于21的数据

db.user.find({age:{$lte:21}})

image-20230126141330900

6、查询id=1 or id=2

db.user.find({$or:[{id:1},{id:2}]})

image-20230126141429638

7、分页查询:Skip()跳过几条,limit()查询条数

跳过1条数据,查询2条数据

db.user.find().limit(2).skip(1)

image-20230126141519851

按照id倒序排序,-1为倒序,1为正序

db.user.find().sort({id:-1})

image-20230126141557350

5.6 索引

为了提高查询效率,MongoDB中也支持索引。

创建索引.

db.user.createIndex({'age':1})

image-20230126141926089

注意:1 :升序索引 -1 :降序索引

查看索引.

db.user.getIndexes()

image-20230126142008926

5.7、执行计划

MongoDB 查询分析可以确保我们建议的索引是否有效,是查询语句性能分析的重要工具。

插入1000条数据。

for(var i=1;i<1000;i++)db.user.insert({id:100+i,username:'name_'+i,age:10+i})

查看执行计划。

db.user.find({age:{$gt:100},id:{$lt:200}}).explain()

image-20230126142758779

测试没有使用索引。

db.user.find({username:'zhangsan'}).explain()

image-20230126142847549

image-20230126143051206

winningPlan:最佳执行计划;
“stage” : “FETCH”, #查询方式,常见的有COLLSCAN/全表扫描、IXSCAN/索引扫描、FETCH/根据索引去检索文档、SHARD_MERGE/合并分片结果、IDHACK/针对_id进行查询

6、SpringData-Mongo

简单的了解MongoDB 的基本命令和索引,我们接下来就要进入到本篇博客当中的重点。

我们要在SpringBoot程序中操作MongoDB, 说到JAVA代码操作MongoDB啊,不外乎两种方式。

  1. 使用官方驱动,类似与使用最基础的JDBC驱动操作mysql这种方式。
  2. 使用Spring Data 提供的Spring Data Mongo DB。

使用第一种方式过于麻烦(本人喜欢偷懒),所以我们使用第二种方式。

Spring-data对MongoDB做了支持,使用spring-data-mongodb可以简化MongoDB的操作,封装了底层的mongodb-driver。

地址:https://spring.io/projects/spring-data-mongodb

使用Spring-Data-MongoDB很简单,只需要如下几步即可:

6.1 环境搭建

6.1.1 创建工程

image-20230126144234631

springBoot版本不要选3.0或3.0以上的,如果你的jdk版本是17或17以上当我没说。

image-20230126144335955

6.1.2 编写YML文件

spring:
  data:
    mongodb:
      uri: mongodb://192.168.136.160:27017/testdb2

6.2 完成基本操作

第一步,编写实体类.

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(value = "tb_person") // 指定实体类和MongoDB集合的映射关系
public class Person {

    @Id
    private ObjectId id;

    @Field("name")
    private String name;

    @Field("age")
    private int age;

    @Field("address")
    private String address;

}

第二步,通过MongoTemplate完成CRUD操作。

这里直接在测试类演示。

	/**
     * 注入模板对象
     */
    @Resource
    private MongoTemplate mongoTemplate;

    /**
     * 增加
     */
    @Test
    public void testSave() {
        for (int i = 0; i < 10; i++) {
            Person person = new Person();

            //ObjectId.get():获取一个唯一主键字符串
            person.setId(ObjectId.get());
            person.setName("张三" + i);
            person.setAddress("北京顺义" + i);
            person.setAge(18 + i);

            mongoTemplate.save(person);
        }
    }

image-20230126200357264

查询所有。

/**
 * 注入模板对象
 */
@Resource
private MongoTemplate mongoTemplate;


/**
 * 查询所有
 */
@Test
public void testFindAll() {
    List<Person> list = mongoTemplate.findAll(Person.class);
    for (Person person : list) {
        System.out.println(person);
    }
}

image-20230126200537409

查询年龄小于20的所有人.

/**
 * 注入模板对象
 */
@Resource
private MongoTemplate mongoTemplate;


/**
 * 查询年龄小于20的所有人
 */
@Test
public void testFind() {

    Query query = new Query(Criteria.where("age").lt(20)); //查询条件对象
    //查询
    List<Person> list = mongoTemplate.find(query, Person.class);

    list.forEach(System.out::println);
}

image-20230126200822318

分页查询.

/**
 * 注入模板对象
 */
@Resource
private MongoTemplate mongoTemplate;


/**
 * 分页查询
 */
@Test
public void testPage() {
    Criteria criteria = Criteria.where("age").lt(30);
    //1、查询总数
    Query queryCount = new Query(criteria);
    long count = mongoTemplate.count(queryCount, Person.class);
    System.out.println(count);
    //2、查询当前页的数据列表, 查询第二页,每页查询2条
    Query queryLimit = new Query(criteria)
            //设置每页查询条数
            .limit(2)
            //开启查询的条数 (page-1)*size
            .skip(2);
    List<Person> list = mongoTemplate.find(queryLimit, Person.class);
    list.forEach(System.out::println);
}

image-20230126201320551

根据id,修改年龄.

image-20230126201446715

/**
 * 注入模板对象
 */
@Resource
private MongoTemplate mongoTemplate;


/**
 * 修改:
 * 根据id,修改年龄
 */
@Test
public void testUpdate() {
    //1、条件
    Query query = Query.query(Criteria.where("id").is("63d26be79e8d6402ffda6b21"));
    //2、修改后的数据
    Update update = new Update();
    update.set("age", 99);
    mongoTemplate.updateFirst(query, update, Person.class);
}

image-20230126201607838

删除:根据id删除。

/**
 * 注入模板对象
 */
@Resource
private MongoTemplate mongoTemplate;


@Test
public void testRemove() {
    Query query = Query.query(Criteria.where("id").is("63d26be79e8d6402ffda6b21"));
    mongoTemplate.remove(query, Person.class);
}

image-20230126201744462

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/180080.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode[128]最长连续序列

难度&#xff1a;中等题目&#xff1a;给定一个未排序的整数数组 nums&#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。请你设计并实现时间复杂度为 O(n)的算法解决此问题。示例 1&#xff1a;输入&#xff1a;nums [100,4,2…

java中new的含义如何理解?

在Java中&#xff0c;new关键字被使用来创建一个新的对象&#xff0c;可以理解为创建的意思。使用关键字new来创建一个对象也叫类的实例化&#xff0c;使用new创建对象时&#xff0c;会调用构造方法初始化对象声明对象Cat cat 在栈内存中实例化对象 new Cat(参数); 在堆内存中每…

C++:类的static成员,友元和构造函数初始化列表

目录 一.类的构造函数的初始化列表 1.类的构造函数初始化列表的引入和介绍 2.初始化列表用于类的类对象成员的拷贝构造函数的调用 3.初始化列表的使用细则 4.使用初始化列表的一个注意事项 二.explicit关键字 三.C类的static成员 1.类中static修饰的成员变量 2.类中st…

Lesson 4.2 逻辑回归参数估计:极大似然估计、相对熵与交叉熵损失函数

文章目录一、逻辑回归参数估计基本思路1. 构建损失函数2. 损失函数求解二、利用极大似然估计进行参数估计三、熵、相对熵与交叉熵1. 熵&#xff08;entropy&#xff09;的基本概念与计算公式2. 熵的基本性质3. 相对熵&#xff08;relative entropy&#xff09;与交叉熵&#xf…

LeetCode[947]移除最多的同行或同列石头

难度&#xff1a;中等题目&#xff1a;n块石头放置在二维平面中的一些整数坐标点上。每个坐标点上最多只能有一块石头。如果一块石头的 同行或者同列 上有其他石头存在&#xff0c;那么就可以移除这块石头。给你一个长度为 n的数组 stones&#xff0c;其中 stones[i] [xi, yi]…

MATLAB算法实战应用案例精讲-【人工智能】Grover量子搜索算法(补充篇)

前言 因为量子计算的并行性, 搜索问题, 比如说数据库搜索, 最短路径问题, 加密问题, 图形着色问题等, 都被视为可以做到量子加速. Grover 算法,有时也称为量子搜索算法(quantum search algorithm),指一种在量子计算机上运行的非结构化搜索算法,是量子计算的典型算法…

LeetCode[765]情侣牵手

难度&#xff1a;困难题目&#xff1a;n对情侣坐在连续排列的 2n个座位上&#xff0c;想要牵到对方的手。人和座位由一个整数数组 row表示&#xff0c;其中 row[i]是坐在第 i 个座位上的人的 ID。情侣们按顺序编号&#xff0c;第一对是 (0, 1)&#xff0c;第二对是 (2, 3)&…

#A. Balanced Lineup排队(rmq模板题)

题目思路建议先看看详解rmq问题很明显这道题意是跟你一段数列&#xff0c;并给出多次询问,询问区间内最大值和最小值的差。如果去暴力枚举显然会超时,所以要用st算法来解决。我们要建立两个RMQ预处理内容&#xff0c;分别处理最大值和最小值。建一个mx[i][j]代表从i开始,长度为…

精品图表Crack:TeeChart ActiveX version 2023.1

TeeChart ActiveX version 2023 数据可视化专家,Visual Studio.Net、Visual Basic、Visual Studio 6和 IIS / ASP的图表组件 概述 TeeChart Pro ActiveX 图表组件库提供数百种 2D 和 3D 图形样式、56 种数学和统计函数供您选择&#xff0c;以及无限数量的轴和 14 个工具箱组件…

DFS(五)最小轮盘锁

752. 打开转盘锁 你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字&#xff1a; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 。每个拨轮可以自由旋转&#xff1a;例如把 9 变为 0&#xff0c;0 变为 9 。每次旋转都只能旋转一个拨轮的一位数字。 锁的初始数字为 0000 &#xff0c;一…

【2023.01.26】定时执行专家 V6.6 兔年春节版 - 更新日志

目录 ◆ 最新版下载链接 ◆ 软件更新日志 – TimingExecutor Full Change Log ▼ 2023-01-23 V6.6 ▼ 2023-01-20 V6.5 ▼ 2022-12-25 V6.4 ▼ 2022-11-15 V6.3 ▼ 2022-10-01 V6.2 ▼ 2022-07-30 V6.1&#xff08;Build 769.30072022&#xff09; ▼ 2022-0…

Linux-Ubuntu入门到精通之远程操作指令

1️⃣shutdown 2️⃣查看或配置网卡信息 3️⃣网卡和IP地址 4️⃣ifconfig 5️⃣ping 6️⃣远程登录和复制文件 7️⃣ ssh 基础&#xff08;重点&#xff09; 8️⃣域名 和 端口号 9️⃣SSH 客户端的简单使用 1️⃣0️⃣Windows 下 SSH 客户端的安装 Putty &#xff1a;http:/…

数据结构 | 海量数据处理 | 位图和哈希切分的常见应用 | 布隆过滤器的使用场景

文章目录位图应用question 1question 2question 3位图的作用哈希切分布隆过滤器作为一种数据结构&#xff0c;哈希桶有着不同于其他数据结构的思想——直接映射&#xff0c;这使得在哈希结构中查找数据的效率达到了最快的O(1)&#xff0c;比起搜索树的比较数据大小&#xff0c;…

数学建模——降维算法

降维 降维的意义 降低无效、错误数据对建模的影响&#xff0c;提高建模的准确性少量切具有代表性的数据将大幅缩减挖掘所需的时间降低存储数据的成本 需要降维的情况 维度灾难。很难有一个简洁的模型在高维空间中依旧具有鲁棒性&#xff0c;而随着模型复杂度的增加&#xf…

【LeetCode每日一题:1663. 具有给定数值的最小字符串~~~递归+DFS+贪心】

题目描述 小写字符 的 数值 是它在字母表中的位置&#xff08;从 1 开始&#xff09;&#xff0c;因此 a 的数值为 1 &#xff0c;b 的数值为 2 &#xff0c;c 的数值为 3 &#xff0c;以此类推。 字符串由若干小写字符组成&#xff0c;字符串的数值 为各字符的数值之和。例如…

你会仲裁吗——劳动仲裁需要准备

目录 劳动仲裁申请书 仲裁思路 ​编辑 一、仲裁前准备 1、自己不认可年终奖 2、自己不认可绩效 二、【仲裁前】协商阶段 1、主张3个月足额年终奖 2、公司协商离职赔偿方案 年终奖仲裁证据 延时加班费 周末加班费 节假日加班费 其他福利-如房补 申请劳动仲裁交通…

uniapp组件传参方式梳理

前言 日常开发中经常会遇到组件之间传递参数问题,整理了几种常见的传参方式,方便日后复习梳理. 常见组件传参的三种方式: 1.父组件向子组件传参 2.子组件向父组件传参 3.子组件向非父组件传参 1.父组件向子组件传参自定义组件: <template><view c…

XPath入门

好久没用XPath了&#xff08;之前没做笔记&#xff09;&#xff0c;最近要用的时候又到处查。。。&#xff08;痛苦.jpg&#xff09;&#xff0c;还是记录下吧&#xff08;π_π&#xff09; XPath&#xff0c;是XML Path Language的缩写&#xff0c; 是一门在 XML 文档中查找…

【Linux】POSIX信号量

目录&#x1f308;前言&#x1f338;1、POSIX信号量&#x1f368;1.1、概念&#x1f367;1.2、PV操作&#x1f33a;2、POSIX信号量相关API&#x1f368;2.1、初始化和销毁信号量&#x1f367;2.2、等待信号量&#xff08;P&#xff09;&#x1f370;2.3、发布信号量&#xff08…

ImmutableList hessian2序列化失败问题分析

问题描述 A服务提供了个RPC接口给B服务使用&#xff0c;入参里有个参数是List类型&#xff0c;B服务在传参时使用Guava里的 ImmutableList&#xff0c;结果发生报错。 其中&#xff0c;B服务即consumer端的异常为&#xff1a;「com.alibaba.dubbo.remoting.RemotingException:…