• rocksdb db.h



    编译


    • https://github.com/facebook/rocksdb/blob/main/INSTALL.md

      如果您计划在生产中运行 RocksDB,请不要使用默认 make 或 make all 进行编译。这将以调试模式编译 RocksDB,这比发布模式慢得多。

    • 默认存在centos7 build和run rocksdb的脚本

      https://github.com/facebook/rocksdb/blob/main/build_tools/setup_centos7.sh

    • 存在编译rocksdb所需环境的ubuntu20 dockerfile

      https://github.com/facebook/rocksdb/blob/main/build_tools/ubuntu20_image/Dockerfile

      mkdir build 
      cd build
      cmake .. #默认是debug模式
      make 
      make install
      
      • 1
      • 2
      • 3
      • 4
      • 5

    测试


    set(SOURCES
            test_util/sync_point.cc
            test_util/sync_point_impl.cc
            test_util/testutil.cc
            test_util/transaction_test_util.cc
    )
    
    if(WITH_TESTS OR WITH_BENCHMARK_TOOLS)
      add_subdirectory(third-party/gtest-1.8.1/fused-src/gtest)
      add_library(testharness STATIC
      test_util/mock_time_env.cc
      test_util/secondary_cache_test_util.cc
      test_util/testharness.cc)
      target_link_libraries(testharness gtest)
    endif()
    
    if(WITH_TESTS)
      set(TESTS
            db/db_basic_test.cc
            env/env_basic_test.cc
      )
      if(WITH_ALL_TESTS)
        list(APPEND TESTS
        	test_util/testutil_test.cc
    	${PLUGIN_TESTS}
        )
      endif()
      set(TESTUTIL_SOURCE
          db/db_test_util.cc
          db/db_with_timestamp_test_util.cc
          monitoring/thread_status_updater_debug.cc
          table/mock_table.cc
          utilities/agg_merge/test_agg_merge.cc
          utilities/cassandra/test_utils.cc
      )
      enable_testing()
      add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
      set(TESTUTILLIB testutillib${ARTIFACT_SUFFIX})
      add_library(${TESTUTILLIB} STATIC ${TESTUTIL_SOURCE})
      target_link_libraries(${TESTUTILLIB} ${ROCKSDB_LIB} ${FOLLY_LIBS})
      if(MSVC)
        set_target_properties(${TESTUTILLIB} PROPERTIES COMPILE_FLAGS "/Fd${CMAKE_CFG_INTDIR}/testutillib${ARTIFACT_SUFFIX}.pdb")
      endif()
      set_target_properties(${TESTUTILLIB}
            PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD_RELEASE 1
            EXCLUDE_FROM_DEFAULT_BUILD_MINRELEASE 1
            EXCLUDE_FROM_DEFAULT_BUILD_RELWITHDEBINFO 1
      )
    
      foreach(sourcefile ${TESTS})
          get_filename_component(exename ${sourcefile} NAME_WE)
          add_executable(${exename}${ARTIFACT_SUFFIX} ${sourcefile})
          set_target_properties(${exename}${ARTIFACT_SUFFIX}
            PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD_RELEASE 1
            EXCLUDE_FROM_DEFAULT_BUILD_MINRELEASE 1
            EXCLUDE_FROM_DEFAULT_BUILD_RELWITHDEBINFO 1
            OUTPUT_NAME ${exename}${ARTIFACT_SUFFIX}
          )
          target_link_libraries(${exename}${ARTIFACT_SUFFIX} testutillib${ARTIFACT_SUFFIX} testharness gtest ${THIRDPARTY_LIBS} ${ROCKSDB_LIB})
          if(NOT "${exename}" MATCHES "db_sanity_test")
            gtest_discover_tests(${exename} DISCOVERY_TIMEOUT 120)
            add_dependencies(check ${exename}${ARTIFACT_SUFFIX})
          endif()
      endforeach(sourcefile ${TESTS})
    
      if(WIN32)
        # C executables must link to a shared object
        if(ROCKSDB_BUILD_SHARED)
          set(ROCKSDB_LIB_FOR_C ${ROCKSDB_SHARED_LIB})
        else()
          set(ROCKSDB_LIB_FOR_C OFF)
        endif()
      else()
        set(ROCKSDB_LIB_FOR_C ${ROCKSDB_LIB})
      endif()
    
      if(ROCKSDB_LIB_FOR_C)
        set(C_TESTS db/c_test.c)
        add_executable(c_test db/c_test.c)
        target_link_libraries(c_test ${ROCKSDB_LIB_FOR_C} testharness)
        add_test(NAME c_test COMMAND c_test${ARTIFACT_SUFFIX})
        add_dependencies(check c_test)
      endif()
    endif()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    cmake_minimum_required(VERSION 3.10)
    
    #project name
    project(MyRocksDBTest)
    
    #specify the require C++ standard
    set(CMAKE_BUILD_TYPE Debug)
    set(CMAKE_CXX_STANDARD 17)
    set(ROCKSDB_DIR /home/baum/rocksdb-gpu-test/rocksdb)
    #set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
    
    link_directories(${ROCKSDB_DIR}/lib)
    
    #find Rocksdb package
    #find_package(RocksDB REQUIRED)
    
    #include the header
    include_directories(${ROCKSDB_DIR}/include ${ROCKSDB_DIR})
    message(STATUS "ROCKSDB_DIR: ${ROCKSDB_DIR}")
    #message(STATUS "ROCKSDB_INCLUDE_DIRS: ${ROCKSDB_INCLUDE_DIRS}") 空值
    
    
    #create the executable
    add_executable(my_test main.cc)
    
    target_link_libraries(my_test rocksdb)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    #第一次测试代码要使用testutil.h文件,这个文件出现一些错误
    //rocksdb测试代码,因为rocksdb没有客户端和服务器,所以没有办法gdb attach process_id
    //https://rocksdb.org/docs/getting-started.html
    //关于打开数据库
    //main.cpp
    #include 
    #include 
    #include "rocksdb/db.h"
    #include "test_util/testutil.h"
    
    
    int main(int argc, char* argv[]) {
      rocksdb::DB* db =nullptr;
      rocksdb::Options options;
      options.create_if_missing = true;
    
      //open  
      rocksdb::Status status =
          rocksdb::DB::Open(options, "./testdb", &db);
      assert(status.ok());
    
      //随机生成器
      rocksdb::Random rnd(static_cast(rocksdb::Env::Default()->NowMicros() & 0xFFFFFFFF));
    
    
      //生成随机的键值
      std::string key=rocksdb::test::RandomKey(&rnd,10);
      std::string value = rocksdb::test::RandomKey(&rnd,20);
    
      //insert
      status = db->Put(rocksdb::WriteOptions(),key,value);
      assert(status.ok());
    
      //query
      std::string result;
      status = db->Get(rocksdb::ReadOptions(),key,&result);
      assert(status.ok());
    
      if(result==value){
        std::cout<<"Query Successful"<
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    //rocksdb测试代码,因为rocksdb没有客户端和服务器,所以没有办法gdb attach process_id
    //https://rocksdb.org/docs/getting-started.html
    //关于打开数据库
    //main.cpp
    #include 
    #include 
    #include 
    #include "rocksdb/db.h"
    //#include "rocskdb/options.h"
    
    
    int main(int argc, char* argv[]) {
      rocksdb::DB* db =nullptr;
      rocksdb::Options options;
      options.create_if_missing = true;
    
      //open  
      rocksdb::Status status =
          rocksdb::DB::Open(options, "./testdb", &db);
      assert(status.ok());
    
      std::string key = "key1";
      std::string value = "value1";
      status = db->Put(rocksdb::WriteOptions(),key,value);
      assert(status.ok());
    
      //query
      std::string result;
      status = db->Get(rocksdb::ReadOptions(),key,&result);
      assert(status.ok());
    
      if(result==value){
        std::cout<<"Query Successful"<
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    源码阅读问题


    Option,DBOption,ColumnFamilyOptions其中有什么区别
    
    • 1

    整体框架

    查看其对外所提供的接口,即头文件部分,先从功能出发,之后去分析为了实现这些功能,都做了什么。

    //db.h
    namespace ROCKSDB_NAMESPACE {
    
    //配置列族的特定行为。rocksdb中的数据可以被组织进不同的列族,每个列族可以有自己的配置
    struct ColumnFamilyOptions; 
    //用于重新组织和优化SST file,减少存储使用并提高读取性能
    struct CompactionOptions;  
    //配置特定范围的压缩行为
    struct CompactRangeOptions;
    //用于配制数据库实例的全局行为,如日志文件位置,并发控制等
    struct DBOptions; 
    //提供了关于外部SST文件的信息。RocksDB支持将SST文件导入和导出,此结构体提供了关于这些文件的元数据
    struct ExternalSstFileInfo;
    //配置了刷新的行为。刷新是将memtable的内容写入SST文件的操作
    struct FlushOptions;
    //这是一个通用结构体,包含了DBOptions和ColumnFamilyOptions的全部选项,为数据库和列族提供了配置
    struct Options;
    //配置读取操作的行为,如是否使用快照、迭代器的行为等
    struct ReadOptions;
    //提供了关于SST表的元数据和统计信息
    struct TableProperties;
    //配置写入操作的行为,如同步写入和禁用WAL
    struct WriteOptions;
    //配置了等待压缩完成的选项
    struct WaitForCompactOptions;
    //这是一个抽象类,提供了与操作系统和底层文件系统的接口
    class Env;
    //这是一个可以被用户扩展的类,用于监听RocksDB的不同事件,如压缩、刷新和写入等
    class EventListener;
    //一个新的抽象层,为RocksDB提供文件系统的操作,允许更灵活地与底层存储进行交互。
    class FileSystem;
    //用于重放RocksDB的操作,这对于故障恢复和测试非常有用
    class Replayer;
    //一个迭代器,用于遍历和检索数据库的统计信息历史
    class StatsHistoryIterator;
    //这两个类分别用于读取和写入RocksDB的操作跟踪,有助于分析和调试
    class TraceReader;
    class TraceWriter;
    //用于表示一组写入操作,允许用户批量地执行多个写入操作,提高写入的效率
    class WriteBatch;
    
    extern const std::string kDefaultColumnFamilyName;
    extern const std::string kPersistentStatsColumnFamilyName;
    struct ColumnFamilyDescriptor {
      std::string name;
      ColumnFamilyOptions options;
      ColumnFamilyDescriptor()
          : name(kDefaultColumnFamilyName), options(ColumnFamilyOptions()) {}
      ColumnFamilyDescriptor(const std::string& _name,
                             const ColumnFamilyOptions& _options)
          : name(_name), options(_options) {}
    };
    
    //对特定列族的一个引用或句柄
    //这个类提供了一系列的虚拟方法,允许你获取关于列族的信息和执行与列族相关的操作
    class ColumnFamilyHandle{
        GetName();
        GetID();
        GetDescriptor();
        GetComparator();
    };
    struct Range{};
    struct RangePtr{};
    
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    API

    class DB{
        +
        //以name的方式打开DB进行reads和writes
        //return ok status or non-ok status
        Status Open(Options,name,dbpstr);
        //以column families的方式打开DB
        Status Open(DBOptions,name,column_families,handles,dbptr);
        //仅仅支持read的实例
        //All DB interfaces that modify data, like put/delete, will return error.还有一些其他操作也是
        Status OpenForReadOnly(Options,name,dbptr,bool);
        Status OpenForReadOnly(DBOptions,name,column_families,handles,dbptr,bool);
        //open DB as secondary instance
        //以辅助实例的形式打开一个 RocksDB 数据库。辅助实例主要用于读取操作,
        //不进行数据库的修改操作。通过正确配置并使用这个功能,可以在不影响主实例
        //正常运行的情况下,对数据库进行查询和分析。注意,调用者需要负责在使用
        //完数据库后释放相关资源。
        Status OpenAsSecondary(Options,name,secondary_path,dbptr);
        //以column families赌注实例的方式打开DB
        Status OpenAAsSecondary(DBOptions,name,secondary_path,column_families,handles,dbptr);
        //这个 API 的设计初衷是为了与 options.CompactionService 结合使用。
        //CompactionService 是 RocksDB 中用于处理压缩任务的服务,
        //这个服务允许用户将压缩操作外包给外部服务以改善性能和资源利用率。
        //这个 API 使得可以通过 CompactionService 触发压缩操作,
        //并将结果输出到指定目录,而不是直接写回数据库。
        //总的来说,这个功能提供了一种在不直接修改数据库的情况下,
        //运行和分析压缩操作结果的能力,这在某些性能调优和资源管理场景中可能非常有用。
        Status OpenAndCompact();
        //该功能允许用户在打开数据库时,剪裁(删除)掉在特定时间戳之后的数据。
        //这个操作主要用于启用了时间戳功能的列族恢复过程中。
        //如果某些输入的列族不支持时间戳,它们将不会发生任何变化。
        //该功能还处于试验阶段
        Status OpenAndTrimHistory(DBOptions,dbname,column_families,handles,dbptr,trim_ts);
        // 手动、同步尝试在写入底层文件系统失败后恢复数据库写操作。
        // 请参见 https://github.com/facebook/rocksdb/wiki/Background-Error-Handling
    	// 如果写操作成功恢复,或者没有需要恢复的突出错误,则返回OK。如果写入错误
        // 不可恢复,则返回底层写入错误。
        // 缺陷:与自动恢复功能不兼容。如果自动恢复正在进行中,将返回 Busy,
        // 而不等待其完成。
        // 请参见 DBOptions::max_bgerror_resume_count 和
        // EventListener::OnErrorRecoveryBegin
        Status Resume();
        //通过释放资源、关闭文件等来关闭数据库
        Status Close();
        //Set the database entry for "key" to "value".
        Status Put(WriteOptions);
        //对于key删除他的实体,如果key不存在,也不会返回error
       	//SingleDelete处于实验阶段,DeleteRange在实际生产中有两个注意事项
        Status Delete(WriteOptions);
        //将数据库中“key”对应的条目与“value”进行合并
        //合并操作是一种延迟执行的操作,意味着合并的结果可能不会立即计算出来。
        //相反,合并操作和操作的数值将被存储在数据库中,直到它们被读取或者通过一次压缩操作被合并。
        //这使得合并操作成为更新计数器、累加数值或者构建集合这类操作的一种高效的方法,
        //特别是当这些操作频繁发生且每次操作的数据量相对较小的时候。
        //允许你将一个新的值与数据库中某个键(key)对应的现有值结合起来,而不是直接替换它
        Status Merge(WriteOptions);
        //包含了控制写操作行为的各种选项。例如,如果options.sync被设置为true,
        //那么在写操作完成后,WAL(Write-Ahead Log,预写日志)将被同步到磁盘,
        //确保数据的持久性
        //允许你将多个更新操作批处理成一个原子操作,以提高性能
        Status Write(WriteOptions,);
        //其主要功能是在RocksDB中查找指定列族("column_family")
        //下某个键("key")对应的值,并将其返回
        //GetName/GetEnv/GetFileSystem()/GetOptions/GetDBOptions
        //GetLatestSequenceNumber(transaction)/GetFullHistoryTsLow
        //GetCreationTimeOfOldestFile
        //GetLiveFilesMetaData:可以获得live SST Files的column family,level,key range ,etc
        //GetLiveFilesStorageInfo
        //GetColumnFamilyMetaData
        //GetAllColumnFamilyMetaData
        //GetLiveFiles/GetSortedWalFiles
        //GetCurrentWalFile
        //...
        //感觉没有我想不到的,阿巴阿巴,需要的时候直接搜吧
        //想记录完全太难了
        Status Get(ReadOptions);
        //虚函数用的挺多的
        // 返回一个在堆上分配的迭代器,用于遍历数据库的内容。
        virtual Iterator* NewIterator(const ReadOptions& options,
                                    ColumnFamilyHandle* column_family) = 0;
        //这个函数用于查询数据库的内部状态和性能相关的信息。通过传入
        //不同的property字符串,用户可以获取数据库大小、内存使用、
        //读写速率等多种不同的信息。
        //前面有关于properties的结构
        virtual bool GetProperty();
        //返回文件系统空间利用大小,所以大概也有mentables中记录的数量
        virtual Status GetApproximateSizes();
        //这个函数提供了一种在不停止数据库的情况下,动态调整数据库配置的方法,从而可以根据实时的需求来优化数据库的性能和行为。
        virtual Status SetOptions();
        //将输入的文件列表(通过文件编号指定)压缩到指定的层级。
        //与 CompactRange() 不同,CompactFiles() 在当前线程
        //执行压缩作业,因此它不被认为是一个“后台”任务
        //应该是指允许用户手动选择特定的文件进行压缩
        virtual Status CompactFiles(CompactionOptions);
        //flush all memtable data
        //FlushWAL
        virtual Status Flush(FlushOptions);
        //WAL->FlushWAL/SyncWAL/LockWAL/UnlockWAL/
        //用于将一系列外部 SST(Sorted String Table)文件加载到
        //数据库中。这个过程主要支持两种模式:
    
    	//覆写模式(默认):在这种模式下,新文件中的重复键将覆写现有键。
        //函数会尝试找到能够容纳这些文件的最低可能层级,并将文件合并到
        //这个层级中。如果文件的键范围与内存表(memtable)的键范围有重叠,就需要首先刷新内存表,然后再进行文件合并。
    
    	//跳过模式(设置 ingest_behind=true):在这种模式下,重复的键
        //将被跳过,文件总是被合并到最底层。这种模式的具体文档
        //可以在 IngestExternalFileOptions::ingest_behind 中找到。
        virtual Status IngestExternalFile();
        virtual Status StartIOTrace(TraceOptions);
        Status DestroyDB(Options);
        Status RepairDB(DBOptions);
        
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 列族column family和列存储的区别?

      • 列族是一种逻辑上的数据组织方式,主要用于提高特定类型数据的读写效率。

      • 列存储是一种物理上的数据存储方式,它通过按列而不是按行存储数据来提高查询性能。

    RocksDB使用的是行存储(Row Store)而非列存储。在RocksDB中,不同的列族可以被认为是独立的键值对空间,但这与列存储中的“列”是不同的概念。

    还需要进一步了解

    • 存在三种定义:
      • database entry
      • key
      • value

    问题


    ppa GPG密钥检索超时

    参考链接:https://www.jianshu.com/p/e2a15336f174

    在这里插入图片描述

    问题在于尝试添加PPA(personal package archive)时,GPG密钥检索超时。

    • 关于ppa的描述,参考:https://www.cnblogs.com/pipci/p/8675569.html

    • ppa网页是https://launchpad.net/

    • 需要注意的是注册有账号之后,返回原先的主页,通过点击页面最下面的launchpad

    请添加图片描述

    • 然后搜索

      请添加图片描述

    • ppa:ubuntu-toolchain-r/test 是一个Personal Package Archive (PPA),它提供了最新版本的GNU编译器集合(GCC)为Ubuntu用户。

    • 修改dockerfile,添加

      RUN echo "deb https://ppa.launchpadcontent.net/ubuntu-toolchain-r/test/ubuntu focal main" |tee -a /etc/apt/sources.list
      RUN echo "deb-src https://ppa.launchpadcontent.net/ubuntu-toolchain-r/test/ubuntu focal main" |tee -a /etc/apt/sources.list
      RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 60C317803A41BA51845E371A1E9377A2BA9EF27F
      RUN add-apt-repository -y ppa:ubuntu-toolchain-r/test
      RUN apt-get update && apt-get upgrade -y
      RUN apt-get install -y gcc-11 g++-11
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

    问题变成了:

    Cannot add PPA - “user or team does not exist”

    在这里插入图片描述

    解决办法:https://github.com/tmatilai/vagrant-proxyconf/issues/171

    dockerfile改为以下这种

    RUN echo "deb https://ppa.launchpadcontent.net/ubuntu-toolchain-r/test/ubuntu focal main" |tee -a /etc/apt/sources.list
    RUN echo "deb-src https://ppa.launchpadcontent.net/ubuntu-toolchain-r/test/ubuntu focal main" |tee -a /etc/apt/sources.list
    RUN curl -sL "http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x60C317803A41BA51845E371A1E9377A2BA9EF27F" |apt-key add
    #RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 60C317803A41BA51845E371A1E9377A2BA9EF27F
    RUN add-apt-repository -y ppa:ubuntu-toolchain-r/test
    RUN apt-get update && apt-get upgrade -y
    RUN apt-get install -y gcc-11 g++-11
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    问题再次变成了:

    在这里插入图片描述
    在这里插入图片描述

    • 设置代理

      export https_proxy=http://
      export http_proxy=http://
      export all_proxy=socks5://
      
      • 1
      • 2
      • 3
    • 问题:GnuTLS recv error

    Cloning into '/root/libprotobuf-mutator'...
    fatal: unable to access 'https://github.com/google/libprotobuf-mutator.git/': GnuTLS recv error (-110): The TLS connection was non-properly terminated.
    
    • 1
    • 2

    解决办法

    ping github.com
    #发现成功连接
    #更新与安装证书
    apt-get update
    apt-get upgrade
    apt-get install --reinstall ca-certificates
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    AJAX基于XML的数据交换、XML和JSON的区别
    风险评估具体操作流程
    物联网主机:为智能交通赋能
    VS+QT编译出现QMYSQL driver not loaded
    Centos7+Hadoop3.3.4+KDC1.15集成认证
    【数据库系统】单表数据查询
    wordpress图片压缩插件-免费批量wordpress图片压缩
    vue当中script setup语法糖
    Breakdance评测:改变游戏规则的WordPress网站生成器
    java-net-php-python-java幼儿早教管理系统查重PPT计算机毕业设计程序
  • 原文地址:https://blog.csdn.net/weixin_40579705/article/details/134044531