Ceph RGW远程同步(multisite)机制研究

Ceph RGW远程同步(multisite)配置 ceph rgw的远程同步(multisite)配置 阅读详情

说明:

   本文基于ceph 10.2.3的;

   远程同步配置,见http://blog.youkuaiyun.com/for_tech/article/details/68927956

   文中以secondary site为本地,所以local和secondary意思相同;remote和source意思相同;


+=======================================================================+

|                     Remote Site (Source Site)                         |
+=======================================================================+



0.1 Pool: {source-zone}.rgw.data.root

    Bucket instances;

0.2 Pool: {source-zone}.rgw.buckets.data

    Objects;

0.3 Pool: {source-zone}.rgw.buckets.index
    For example, we have 4 buckets, each bucket has 3 shards (rgw_override_bucket_index_max_shards=3)
    bucket-0 shard0     .dir.{key-of-bucket-0}.0
    bucket-0 shard1     .dir.{key-of-bucket-0}.1
    bucket-0 shard2     .dir.{key-of-bucket-0}.2
    bucket-1 shard0     .dir.{key-of-bucket-1}.0
    bucket-1 shard1     .dir.{key-of-bucket-1}.1
    bucket-1 shard2     .dir.{key-of-bucket-1}.2
    bucket-2 shard0     .dir.{key-of-bucket-2}.0
    bucket-2 shard1     .dir.{key-of-bucket-2}.1
    bucket-2 shard2     .dir.{key-of-bucket-2}.2
    bucket-3 shard0     .dir.{key-of-bucket-3}.0
    bucket-3 shard1     .dir.{key-of-bucket-3}.1
    bucket-3 shard2     .dir.{key-of-bucket-3}.2

0.4 Pool: {source-zone}.rgw.log

for example, rgw_data_log_num_shards=4

    data_log.0
    data_log.1
    data_log.2
    data_log.3

0.5 map between bucket shards to data log shards 

    there are

         {bucket-number}*rgw_override_bucket_index_max_shards (12 in our example)
    bucket shards, and
         rgw_data_log_num_shards (4 in our example)
    data log shards;

    These bucket shards are mapped to these data log shards, see function choose_oid()

        bucket-0 shard0 -------- \
        bucket-0 shard1            \
        bucket-0 shard2              \
        bucket-1 shard0                \
        bucket-1 shard1                   data_log.0
        bucket-1 shard2     map to        data_log.1
        bucket-2 shard0                   data_log.2
        bucket-2 shard1                   data_log.3
        bucket-2 shard2                /
        bucket-3 shard0              /
        bucket-3 shard1            /
        bucket-3 shard2 -------- /

      Important: there are 2 kinds of shards:
            data-log-shard:  [0, rgw_data_log_num_shards)
            bucket-shard  :  [0, rgw_override_bucket_index_max_shards)

0.6 Writing an object 

    When an object (OBJ_444) in put into bucket-B, shardS

     A. the object is written into pool  {source-zone}.rgw.buckets.data
     B. write log into pool={source-zone}.rgw.buckets.index, obj=.dir.{key-of-bucket-B}.S as KV pairs:
            OBJ_444             ==> info of OBJ_444, such as owner, content-type ...
            .0_00000000001.4.2  ==> write OBJ_444 state=CLS_RGW_STATE_PENDING_MODIFY
            .0_00000000002.5.3  ==> write OBJ_444 state=CLS_RGW_STATE_COMPLETE
        update omap header to

            .0_00000000002.5.3

        Important: these logs are written by the "Ceph classes", so that the markers (the omap key, such as
           .0_00000000001.4.2, .0_00000000002.5.3) are guaranteed ordered. The order is the key to sync data

           between sites (secondary site needs to process the logs in the same order.)

           "Ceph Classes": Ceph loads .so classes stored in the osd class dir directory dynamically
           (i.e., $libdir/rados-classes by default). When you implement a class, you can create new
           object methods that have the ability to call the native methods in the Ceph Object Store,
           or other class methods you incorporate via libraries or create yourself. On writes, Ceph
           Classes can call native or class methods, perform any series of operations on the inbound
           data and generate a resulting write transaction that Ceph will apply atomically. On reads,
           Ceph Classes can call native or class methods, perform any series of operations on the
           outbound data and return the data to the client.

     C. If bucket-B shardS is mapped to data_log.X, then
        write log into  pool={source-zone}.rgw.log,  obj=data_log.X as KV pair
            1_1489979397.374156_23.1 ==> some info like bucket-B shardS has modification, timestampT
        update omap header to

            1_1489979397.374156_23.1

        Important: these logs are written by the "Ceph classes", so that the markers (the omap key, such as
           1_1489979397.374156_23.1) are guaranteed ordered. The order is the key to sync data between 

           sites (secondary site needs to process the logs in the same order.)


      Important: the data log shard and bucket shard are very similar in that:
            modifications are logged as KV paris;

            latest marker are recorded as omap header;

            the markers are guaranteed ordered. 



+=======================================================================+
|                     Local Site (Secondary Site)                       |
+=======================================================================+


0.8 Pool {secondary-zone}.rgw.log

  0.8.1 the mapping between bucket shard to data log shard (for full sync)

    data.full-sync.index.{source-zone-id}.0    -----   remote data_log.0
    data.full-sync.index.{source-zone-id}.1    -----   remote data_log.1
    data.full-sync.index.{source-zone-id}.2    -----   remote data_log.2
    data.full-sync.index.{source-zone-id}.3    -----   remote data_log.3   

    For example:

    # rados  -p {secondary-zone}.rgw.log listomapkeys data.full-sync.index.{source-zone-id}.1
      testbuckAAA:{key-of-bucket-testbuckAAA}:0
      testbuckAAA:{key-of-bucket-testbuckAAA}:2
      testbuckCCC:{key-of-bucket-testbuckCCC}:1
    that's to say, the following 3 bucket shards are mapped to data log shard 1
      testbuckAAA, shard0
      testbuckAAA, shard2
      testbuckCCC, shard1

  0.8.2  current marker of data log shards

    datalog.sync-status.shard.{source-zone-id}.0    -----   remote data_log.0
    datalog.sync-status.shard.{source-zone-id}.1    -----   remote data_log.1
    datalog.sync-status.shard.{source-zone-id}.2    -----   remote data_log.2
    datalog.sync-status.shard.{source-zone-id}.3    -----   remote data_log.3
  0.8.3 current marker (inc_marker, full_marker) of bucket shards as xattrs
    bucket.sync-status.{remote-zone-id}:{bucket-0}:{bucket_id}:0  ---- bucket-0 shard0
    bucket.sync-status.{remote-zone-id}:{bucket-0}:{bucket_id}:1  ---- bucket-0 shard1
    bucket.sync-status.{remote-zone-id}:{bucket-0}:{bucket_id}:2  ---- bucket-0 shard2
    bucket.sync-status.{remote-zone-id}:{bucket-1}:{bucket_id}:0  ---- bucket-1 shard0
    bucket.sync-status.{remote-zone-id}:{bucket-1}:{bucket_id}:1  ---- bucket-1 shard1
    bucket.sync-status.{remote-zone-id}:{bucket-1}:{bucket_id}:2  ---- bucket-1 shard2
    bucket.sync-status.{remote-zone-id}:{bucket-2}:{bucket_id}:0  ---- bucket-2 shard0
    bucket.sync-status.{remote-zone-id}:{bucket-2}:{bucket_id}:1  ---- bucket-2 shard1
    bucket.sync-status.{remote-zone-id}:{bucket-2}:{bucket_id}:2  ---- bucket-2 shard2
    bucket.sync-status.{remote-zone-id}:{bucket-3}:{bucket_id}:0  ---- bucket-3 shard0
    bucket.sync-status.{remote-zone-id}:{bucket-3}:{bucket_id}:1  ---- bucket-3 shard1
    bucket.sync-status.{remote-zone-id}:{bucket-3}:{bucket_id}:2  ---- bucket-3 shard2

Example:

----------------------------------At source site----------------------------------

   A. assume that these 3 bucket shard are mapped to data log shard 1.
           bucket-2 shard0
           bucket-2 shard1
           bucket-0 shard2
   B.  write BJ_444 into bucket-2 shard0
       write BJ_555 into bucket-2 shard1
       write BJ_666 into bucket-2 shard1
       write BJ_777 into bucket-0 shard2
   C. data_log.1 records the modifications:
     i. The omap header of data_log.1 records the marker of the latest modification:
             1_1490781936.075013_25.2
     ii. the omap KV pairs records the modifications:
       # rados -p {source-zone}.rgw.log  listomapkeys data_log.1
       1_1490781929.259023_21.1  ==>  some info like bucket-2 shard0 has modification, timestamp1
       1_1490781929.282654_22.1  ==>  some info like bucket-2 shard1 has modification, timestamp2
       1_1490781936.075013_25.1  ==>  some info like bucket-2 shard1 has modification, timestamp3
       1_1490781936.075013_25.2  ==>  some info like bucket-0 shard2 has modification, timestamp4
   D. the bucket shard records the modifications of each bucket shard
       .dir.{key-of-bucket-2}.0:   --> bucket-2 shard0
           the omap header records the marker of the latest modification
                0_00000000002.6.3
           the KV pairs records the modifications:
                OBJECT_444         ==> info of OBJ_444, such as owner, content-type ...
                0_00000000001.5.2  ==> write OBJ_444 state=CLS_RGW_STATE_PENDING_MODIFY
                0_00000000002.6.3  ==> write OBJ_444 state=CLS_RGW_STATE_COMPLETE
       .dir.{key-of-bucket-2}.1:   --> bucket-2 shard1
           the omap header records the marker of the latest modification
                0_00000000004.10.3
           the KV pairs records the modifications:
                OBJECT_555         ==> info of OBJ_555, such as owner, content-type ...
                OBJECT_666         ==> info of OBJ_666, such as owner, content-type ...
                0_00000000001.5.2  ==> write OBJ_555 state=CLS_RGW_STATE_PENDING_MODIFY
                0_00000000002.6.2  ==> write OBJ_555 state=CLS_RGW_STATE_PENDING_MODIFY
                0_00000000003.8.3  ==> write OBJ_666 state=CLS_RGW_STATE_COMPLETE
                0_00000000004.10.3 ==> write OBJ_666 state=CLS_RGW_STATE_COMPLETE
       .dir.{key-of-bucket-0}.2:  --> bucket-0 shard2
           the omap header records the marker of the latest modification
                0_00000000002.6.3
           the KV pairs records the modifications:
                OBJECT_777         ==> info of OBJ_777, such as owner, content-type ...
                0_00000000001.1.2  ==> write OBJ_777 state=CLS_RGW_STATE_PENDING_MODIFY
                0_00000000002.2.3  ==> write OBJ_777 state=CLS_RGW_STATE_COMPLETE

----------------------------------At secondary site----------------------------------
   A. datalog.sync-status.shard.{source-zone-id}.1 records the marker that has been synced.
       # rados -p {secondary-zone}.rgw.log get datalog.sync-status.shard.{source-zone-id}.1 file
       # cat file
           1_1490781929.259023_21.1
       It means that, marker 1_1490781929.259023_21.1 has been synced.

   B. The sync thread will request omap header of data_log.1 from source zone, and it will get:
           1_1490781936.075013_25.2
      Because
           1_1490781936.075013_25.2 > 1_1490781929.259023_21.1
      it knows there are data to sync. Then it lists omap KV pairs of data_log.1 from source zone,
      and it will get,
           1_1490781929.282654_22.1
           1_1490781936.075013_25.1
           1_1490781936.075013_25.2
      then it knows,
        bucket-2 shard1 has modification, timestamp2
        bucket-2 shard1 has modification, timestamp3
        bucket-0 shard2 has modification, timestamp4

   C. take bucket-2 shard1 for example (bucket-0 shard2 is similar). A marker
      was recorded locally at bucket.sync-status.{remote-zone-id}:{bucket-2}:{bucket_id}:1
             0_00000000001.5.2
      then, it lists logs of .dir.{key-of-bucket-2}.1 from source zone starting
      at maker 0_00000000001.5.2, and it gets:
                0_00000000001.5.2  ==> write OBJ_555 state=CLS_RGW_STATE_PENDING_MODIFY
                0_00000000002.6.2  ==> write OBJ_555 state=CLS_RGW_STATE_PENDING_MODIFY
                0_00000000003.8.3  ==> write OBJ_666 state=CLS_RGW_STATE_COMPLETE
                0_00000000004.10.3 ==> write OBJ_666 state=CLS_RGW_STATE_COMPLETE
      process these logs one by one,
                for CLS_RGW_STATE_PENDING_MODIFY, skip;
                for CLS_RGW_STATE_COMPLETE, sync this obj;


+==================================================================+
|              Secondary Site code                                 |
+==================================================================+

RGWDataSyncCR:

1.  RGWReadDataSyncStatusCoroutine

  1.1 read local ceph cluster (RGWReadDataSyncStatusCoroutine)
            local pool: {secondary-zone}.rgw.log
            local obj: datalog.sync-status.{remote-zone-id}
      to get 'state' and 'num_shards', and save into
      sync_status.sync_info (see parent class RGWSimpleRadosReadCR)
  1.2 for each data-log-shard X, read the content of following object in local ceph cluster,
            local pool: {secondary-zone}.rgw.log
            local obj: datalog.sync-status.shard.{remote-zone-id}.X
      to get state(full or increment sync), marker, next_step_marker,
      timestamp ... and save into sync_status->sync_markers[X]

2 (if 'state' got in 1.1 is StateInit), RGWInitDataSyncStatusCoroutine
  2.1  lock datalog.sync-status.{remote-zone-id}  (the same obj in step 1.1)
  2.2  recreate datalog.sync-status.{remote-zone-id}
  2.3  lock it again
  2.4  for each data-log-shard X, read remote ceph cluster
            remote pool: {source-zone}.rgw.log
            remote obj:  data_log.X
       and save into shards_info[X]
  2.5  for each data-log-shard X, save shards_info[X] to local ceph cluster,
            local pool: {secondary-zone}.rgw.log
            local obj : datalog.sync-status.shard.{remote-zone-id}.X
       Notice: See step 1.2, they are the same objs.
       What is done by 2.4 and 2.5?
             Remote                           Local
           data_log.0      ====>    "datalog.sync-status.shard.{remote-zone-id}.0"
           data_log.1      ====>    "datalog.sync-status.shard.{remote-zone-id}.1"
           data_log.2      ====>    "datalog.sync-status.shard.{remote-zone-id}.2"
           ......
           data_log.N      ====>    "datalog.sync-status.shard.{remote-zone-id}.N"    N = rgw_data_log_num_shards
  2.6  change  sync_status.sync_info.state to StateBuildingFullSyncMaps, and
       save into local ceph cluster:
            local pool: {secondary-zone}.rgw.log
            local obj: datalog.sync-status.{remote-zone-id}
       Notice: See step 1.1, it's the same obj. Now, we are changing the state.
  2.7  unlock datalog.sync-status.{remote-zone-id}  (the same obj in step 1.1, 2.1)

3 (if 'state' got in 1.1 is StateBuildingFullSyncMaps), RGWListBucketIndexesCR
  Notice: if the multisite is configured when source/remote zone is empty,
          step 3 does nothing, because there is no data when bulding the full
          sync maps.
  3.1  create entries_index (RGWShardedOmapCRManager), it stands for the objs in local ceph cluster:
                local pool: {secondary-zone}.rgw.log
                local objs:
                      data.full-sync.index.{remote-zone-id}.0
                      data.full-sync.index.{remote-zone-id}.1
                      ...
                      data.full-sync.index.{remote-zone-id}.N     N = rgw_data_log_num_shards
       entries_index->append(key, X) is to set omap
                      key: key
                      val: empty
       to object:
                      data.full-sync.index.{remote-zone-id}.X
  3.2  list bucket instances from remote zone (call RGWReadRESTResourceCR with no key).
                 remote pool: {source-zone}.rgw.data.root
                 remote objs:
                              .bucket.meta.{bucket-name-A}:{remote-zone-id}.4133.1
                              .bucket.meta.{bucket-name-B}:{remote-zone-id}.4139.2
                              .bucket.meta.{bucket-name-C}:{remote-zone-id}.4138.3
                              ......
        a list of bucket instances are returned:
                 {bucket-name-A}:{remote-zone-id}.4133.1
                 {bucket-name-B}:{remote-zone-id}.4139.2
                 {bucket-name-C}:{remote-zone-id}.4138.3
                 ......
  3.3 for each bucket instance returned in step 3.2, e.g.
                 {bucket-name-A}:{remote-zone-id}.4133.1
      get the detail info about it.
      (call RGWReadRESTResourceCR with key="{bucket-name-A}:{remote-zone-id}.4133.1")
      detail info includes:
                 num_shards of bucket-name-A;
                 name of bucket-name-A;
                 index pool, data pool, ... of bucket-name-A;
      3.3.1 for i in [0, num_shards), for example,
                 bucket-name-A, shard-i is mapped to X.
            then, set omap (by 'entries_index', see step 3.1)
                 key: {bucket-name-A}:{remote-zone-id}.4133.1
                 val: empty
            to local obj:
                 local pool: {secondary-zone}.rgw.log
                 local obj : data.full-sync.index.{remote-zone-id}.X
       At last, data.full-sync.index.{remote-zone-id}.X     0 <= X < rgw_data_log_num_shards
       records at source/remote site, which [bucket shard] are mapped to X.  For example:
            # rados -p {zone}.rgw.log listomapkeys data.full-sync.index.{remote-zone-id}.3
                testbuckAAA:900d449b-3c56-4949-8b88-bc8a6d4ee3b1.4122.1:1
                testbuckAAA:900d449b-3c56-4949-8b88-bc8a6d4ee3b1.4122.1:5
                testbuckBBB:900d449b-3c56-4949-8b88-bc8a6d4ee3b1.4123.2:1
                testbuckBBB:900d449b-3c56-4949-8b88-bc8a6d4ee3b1.4123.2:5
                testbuckCCC:900d449b-3c56-4949-8b88-bc8a6d4ee3b1.4124.3:1
                testbuckCCC:900d449b-3c56-4949-8b88-bc8a6d4ee3b1.4124.3:5
       that is to say,
                testbuckAAA, shard1
                testbuckAAA, shard5
                testbuckBBB, shard1
                testbuckBBB, shard5
                testbuckCCC, shard1
                testbuckCCC, shard5
        are mapped to X, at remote site.
  3.4 for each data-log-shard X, there are a number of [bucket, shard] mapped to X,
      then, save the number in local obj:
            local pool: {secondary-zone}.rgw.log
            local obj : datalog.sync-status.shard.{remote-zone-id}.X

4 (if 'state' got in 1.1 is StateSync),  for each data-log-shard X,
         RGWDataSyncShardControlCR -->
         RGWDataSyncShardCR 
  4.1 RGWDataSyncShardCR::incremental_sync
  4.1.1 create an error repository, error_repo: datalog.sync-status.shard.{remote-zone-id}.X.retry
        error_repo->append(key) is to set an omap KV pair (key=key, val=empty)
        failed bucket shards will be appended here, and will be processed (retried) at 4.1.5
  4.1.2 lock local obj "datalog.sync-status.shard.{remote-zone-id}.X" for a period of lock_duration
  4.1.3 create a marker_tracker (RGWDataSyncShardMarkerTrack);  it's used to
         i.  check if a bucket shard is in progress. See 4.1.9;  2.
         ii. update the maker.  See 4.1.7  and 4.1.9.C
  4.1.4 process out of band updates (Yuanguo: generated by notification ??)
  4.1.5 process bucket shards that previously failed.
  4.1.6 read omap header of the following object from remote zone
              remote pool: {source-zone}.rgw.log
              remote obj : data_log.X
        The map header contains:
              string max_marker;
              utime_t max_time;
  4.1.7 if the data log marker got in 4.1.6 is NOT newer than what was recorded locally,
        this round of incremental sync is finished.
        See 1.2, where the recorded markers were read from local ceph cluster.
               local pool: {secondary-zone}.rgw.log
               local obj: datalog.sync-status.shard.{remote-zone-id}.X
               Yuanguo: where did these markers get updated ???
                  Answer: the marker_tracker, See 4.1.3 and 4.1.9.C
  4.1.8 else, if the data log marker got in 4.1.6 is newer than what was recorded locally
        read omap KV paris of the following object from remote zone
              remote pool: {source-zone}.rgw.log
              remote obj : data_log.X
        What are the KV pairs? See RGWDataChangesLog::add_entry. They are:
              1_1489653363.684562_381.1 => some info including bucke-tname, bucked-id, bucket-shard, modification timestamp
              Notice the key of KV pair is not 'change.key', but generated at: cls/log/cls_log.cc:cls_log_add
        The longer story: we have B buckets, each has rgw_override_bucket_index_max_shards shards, then
                hash(bucket-N, S) = D     the hash is function choose_oid()
                    S is the 'bucket-shard', D is the 'data-log-shard', and
                    0 <= N < B  <------ all buckets
                    0 <= S < rgw_override_bucket_index_max_shards  <------ all shards of all buckets
                    0 <= D < rgw_data_log_num_shards  <------- all shards of all buckets are sharded into [0, rgw_data_log_num_shards)
              that is to say, any modification of a bucket will be recorded as omap KV pair of exactly one "data_log.[0-rgw_data_log_num_shards)"
              we are consitering the specific data_log.X now, and we may get something like:
                    1_1490768507.881727_3.1 => some info like bucket-2 shard3 has modification timestamp1
                    1_1490768519.257779_4.1 => some info like bucket-5 shard1 has modification timestamp2
                    1_1490768527.759371_5.1 => some info like bucket-1 shard4 has modification timestamp3
                    1_1490768541.378290_6.1 => some info like bucket-6 shard0 has modification timestamp4
                    ......
  4.1.9 For any entry returned in 4.1.8 (it's some info like: 1_1490768519.257779_4.1 => some info like bucket-5 shard1 has modification timestamp2)
        if it's not already in progress (checked by the marker_tracker created in 4.1.3) or not duplicated,
        handle it by RGWDataSyncSingleEntryCR.
           A. parse the entry to get bucket-name:bucket-5, bucket-shard:shard1,
           B. call RGWRunBucketSyncCoroutine
               a. get xattrs from local ceph cluster (RGWReadBucketSyncStatusCoroutine)
                       local pool: {secondary-zone}.rgw.log
                       local obj : bucket.sync-status.{remote-zone-id}:{bucketname}:{bucket_id}:{shard_id}
                  the xattrs include:
                       full_marker
                       inc_marker
                       lock.sync_lock
                       lock.sync_lock.incremental
                       state
                  if a bucket shard is empty, there will be no obj: bucket.sync-status.{remote-zone-id}:{bucketname}:{bucket_id}:{shard_id}
                  in this case, state will be StateInit. That's to say, when you put the first object in a bucket shard, a full sync of this
                  bucket shard will be triggered.
               b. get bucket instance info from local ceph cluster, if not present ...
               c. if state got in step a is StateInit,
                      call RGWInitBucketShardSyncStatusCoroutine
                            lock obj=bucket.sync-status.{remote-zone-id}:{bucketname}:{bucket_id}:{shard_id}
                            recreate that obj
                            lock obj again;
                            read bucket index log info from remote zone;
                            write what's read above in local ceph cluster;
                            unlock obj
                      set state as StateFullSync (do full sync next time)
               d. if state got in step a is StateFullSync,
                      call RGWBucketShardFullSyncCR
                      set state as StateIncrementalSync (do incremental sync next time)
               e. if state got in step a is StateIncrementalSync,
                      call RGWBucketShardIncrementalSyncCR
                            lock obj=bucket.sync-status.{remote-zone-id}:{bucketname}:{bucket_id}:{shard_id} a period of lock_duration
                            create another marker_tracker(we call it {marker_tracker}_1) (RGWBucketIncSyncShardMarkerTrack),
                                  unlike the marker_tracker in step 4.1.3 (update marker of data log shard), it used to update
                                  marker of the bucket shard.
                            list bucket shard logs from source/remote zone, that is omap KV pairs of
                                   remote pool: {source_zone}.rgw.buckets.index
                                   remote obj : .dir.{key-of-bucket-B}.S
                            for each entry returned, syncing that obj if it's CLS_RGW_STATE_COMPLETE;
                            {marker_tracker}_1->flush(), that's to update the marker in obj:
                                   local pool: {secondary_zone}.rgw.log
                                   local obj : bucket.sync-status.{remote-zone-id}:{bucket-0}:{bucket_id}:0
           C. marker_tracker->finish ---> ... ---> marker_tracker->store_marker.
              Update new marker as content of the following object in local ceph cluster (See 4.1.3 and 4.1.7)
                   local pool: {secondary-zone}.rgw.log
                   local obj:  datalog.sync-status.shard.{remote-zone-id}.X
Simlink与PX4硬件在环仿真(HIL)实现 Simlink与PX4硬件在环仿真(HIL)实现 介于涉及的知识比较多,这里只是简单的介绍一下,更多内容可以参考阿木实验室《基于matlab模型开发》课程。 硬件在环HIL介绍 simlink与PX4通信实现 硬件在环HIL介绍 为来贯彻万物都可以用数学公式表示,我们以simlink的角度来看我们的无人机,那么UAV可以分为以下的几个模块: 传感器模型 滤波器模块 控制器模... 阅读详情

相关推荐

【图数据库与知识图谱入门】2.2 图数据库 vs. 关系型数据库 vs. NoSQL数据库

本文对比了关系型数据库、NoSQL数据库和图数据库的核心差异与应用场景。关系型数据库以二维表结构为核心,适合结构化数据的事务处理(如MySQL),但多表关联查询性能随层级增加而下降。NoSQL数据库(如MongoDB)具有灵活schema,适合海量非结构化数据存储,但关联查询能力较弱。图数据库专注于节点-边关系建模,擅长处理复杂关联分析(如社交网络)。通过学生-课程案例展示了MySQL的多表JOIN操作和MongoDB的两种关联实现方式(内嵌文档和文档引用),揭示了不同数据库在数据关联处理上的本质区别。

kngines 1541

趣解 ceph rgw multisite data sync 机制

multisite是ceph rgw对象数据异地容灾备份的一个有效方案,笔者希望深入理解该技术,并应用于生产环境中,然而rgw的这部分代码晦涩难懂,笔者多次尝试阅读,仍云里雾里不解其意,最终流着泪咬着牙坚持多看了几遍,总结出了data sync的流程,这里以通俗易懂的形式呈现出来,希望对大家有所帮助~ 首先,认识下 data sync机制 的三个角色Data、DataLogShard、BucketShard rgw的multisite同步分为两部分:metadata数据同步 和 d...

lv0918_qian的博客 1335

04目标检测-Two-stage的目标检测算法

前面我们对进行了对比分析,同时上一篇我们介绍了传统算法在目标检测的原理和效果,此篇我们记录了我学习目标检测算法的深度,深入讲述一下深度学习算法在目标检测的原理和效果。原文链接:https://blog.youkuaiyun.com/qq_41946216/article/details/132800752。版权声明:本文为优快云博主「爱吃面的猫」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。One-stage(YOLO和SSD系列):直接回归目标位置。

qq_41946216的博客 3650

rgw bucket sync

1. c创建bucketà(元数据是否同步到对端?)—>disableà(已同步的元数据是否还在)—>写数据(数据是否同步到对端)àenable(刚才写入的数据是否同步到对端了)àdisable(写入的数据还在对端?) 结果:rados ls -p second.rgw.meta --namespace root 两端可以看到由新建的bucket信息—>再次执行命令两端可以看...

huangaijuan1的博客 909

在 Ubuntu 上安装和配置 PostgreSQL 实录

本文介绍了在Ubuntu系统上安装和配置PostgreSQL数据库的完整步骤。主要内容包括:1)通过官方源或PPA源安装最新版本;2)修改配置文件(postgresql.conf和pg_hba.conf)以允许远程访问;3)设置postgres用户密码;4)创建新用户并配置权限;5)防火墙设置和重启服务;6)验证安装和远程连接方法。文章提供了详细的命令行操作指导,帮助用户完成从安装到远程访问的全部配置过程。

qq_58168857的博客 1203

Android 13 GMS认证避坑:手把手教你搞定RKP配置,解决GTS测试fail

本文详细解析Android 13 GMS认证中的RKP(远程密钥配置)全流程,提供GTS测试失败的深度解决方案。从RKP核心概念到实战配置技巧,帮助开发者规避常见陷阱,确保设备顺利通过Google安全认证,特别适合需要快速掌握Android13 GMS认证的工程师参考。

weixin_29796279的博客 462

Ceph 14.2.22:对象存储中多站点功能的介绍与使用

本文详细介绍如何搭建ceph多站点功能。

分布式存储随笔 1297

论文选题难?7种AI加持的万能选题法(全专业通用+工具实测)

AI时代学术选题新范式:7大智能方法破解研究痛点 传统选题方法面临范围失控、资料难寻、创新不足三大痛点,本文提出AI赋能的7种选题方法论: 1.现象+群体法:自动抓取热点与人群特征 2.理论+场景法:经典理论与新兴场景匹配 3.技术+问题法:前沿技术与领域痛点结合 4.对比+变量法:时空维度与变量关系分析 5.热点+理论法:事件传播与理论深挖融合 6.微调+变量法:已有选题变量置换创新 7.AI全流程法:关键要素智能迭代生成 同时警示AI使用的伦理边界,需规避虚构文献、伪造数据等风险,并提供针对本科生、研究

Conan_0728的博客 1879

Ceph 对象存储多站点复制:第二部分

新钛云服已累计为您分享833篇技术干货系列回顾与目标在本系列的第一部分中,我们介绍了Ceph对象存储的多站点特性,并准备好了用于部署和配置Ceph对象多站点异步复制的实验环境。第二部分将详细讲解如何在两个Ceph集群之间建立初始的多站点复制配置,如下图所示:Ceph 对象存储多站点初始配置概述自Quincy版本起,Ceph引入了一个名为rgw的新管理器模块,集成在cephadm编排器中。该模块简化...

NewTyun的博客 1044

【QT开发教程】使用Qt进行蓝牙低功耗(BLE)编程

蓝牙低功耗(BLE,Bluetooth Low Energy)技术广泛应用于现代设备中,例如智能手表、健身追踪器和物联网设备。Qt提供了一套完整的Bluetooth模块,使开发者可以轻松地在应用程序中实现BLE通信功能。本文将介绍如何在Qt中进行BLE编程,包括基本概念、使用方法以及一些实际的示例。

科技改变人类,技术成就未来 2868

基于 C# 实现 RTSP 摄像头监控分屏系统:从流媒体获取到多画面显示

通过本文的讲解,我们介绍了如何在 C# 中实现 RTSP 摄像头监控分屏系统。我们使用了FFmpeg和VLC两种不同的方法来获取和解码 RTSP 流,并通过PictureBox控件和控件实现了分屏布局。两种解码方案都非常强大,可以根据实际需求选择最适合的方案。通过这种方式,您可以轻松地在 C# 中集成 RTSP 流,并将多个摄像头的视频流实时显示在同一屏幕上,进行监控和分析。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 2307

RadosGW的Sync Module浅析

RadosGW的Sync Module浅析 文章目录RadosGW的Sync Module浅析参考资料Sync Module的载入Sync Module的初始化Sync Module的数据操作实现一个Sync Module的基本改动 参考资料 Ceph RGW远程同步(multisite)机制研究 Ceph RGW multisite代码实现 Realm和Period Ceph v12.2.12...

JeegnChen的博客 989

A*寻路算法的最简单通俗讲解

为什么我的眼里常含泪水?因为我有一个算法不会。为了节约点眼泪,今天我们就来介绍著名的A*寻路算法(或简称A*算法)。 Peter Hart, Nils Nilsson 和 Bertram Raphael 在1968年首次提出了著名的A*算法。A*算法其实是Dijkstra最短路径算法的一种扩展。不一样的是,在A*算法中我们需要使用Heuristics 来导引搜索过程,以期达到更好的表现。 ...

白马负金羁 2万+

Ceph 之Multisite 下的bucket reshard

目录 一、背景和问题 二、bucket reshard 过程 主集群信息汇总 Multisite 下手动reshard References 一、背景和问题 默认情况下只有当单个bucket承载的object数量过多,导致o...

weixin_30399871的博客 565

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

腾讯云存储专家深度解读基于Ceph对象存储的混合云机制

背景毫无疑问,乘着云计算发展的东风,Ceph已经是当今最火热的软件定义存储开源项目。如下图所示,它在同一底层平台之上可以对外提供三种存储接口,分别是文件存储、对象存储以及块存储,本文主要关注的是对象存储即radosgw。基于Ceph可方便快捷地搭建安全性好、可用性高、扩展性好的私有化存储平台。私有化存储平台虽然以其安全性的优势受到越来越多的关注,但私有化存储平台也存在诸多弊端。例如在如下场景中,某...

karamos的专栏 1813

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Ceph RGW 多站点同步策略(Multisite Sync Policy)完全指南:从 Zonegroup 粗粒度同步到 Bucket 级精细控制

Ceph RADOS Gateway(RGW)的多站点同步策略(Multisite Sync Policy)是自 Octopus 版本引入的、用于精细控制跨 Zone 桶间数据流动的机制。它通过"同步策略组(Sync Policy Group)— 数据流(Data Flow)— 管道(Pipe)"三级模型,取代了旧版 zonegroup 层级的粗粒度 `sync_from*` 配置,支持桶之间产生

gitblog_00925的博客 320

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

ceph rgw java_ceph rgw multisite基本用法

Realm: Zonegroup: 理解为数据中心,由一个或多个Zone组成,每个Realm有且仅有 一个Master Zonegroup,用于处理系统变更,其他的称为Slave Zonegroup,元数据与Master Zonegroup保持一致;Zone: Zone是一个逻辑概念,包含一个或者多个RGW实例。每个Zonegroup有且仅有一个Master Zone,用于处理bucket和use...

weixin_39587113的博客 356

ceph rgw reshard (by quqi99)

所以L 版在后面的一个pr 禁用了multisite 下自动的reshard1。bucket里的object太多了,导致它的metadata omap index太多(包含6 million+ keys, 比建议的多了60倍, objectcacher用于在客户端缓存omap - https://blog.youkuaiyun.com/quqi99/article/details/140525441), 进而造成超时,进而OSD之间无法发heartbean, 这些OSD报告失败,并且OSD反复down and up。

技术并艺术着 1445

Ceph RGW多区部署实战:从概念原理到排障调优

对象存储的高可用与灾备往往依赖多区域部署能力,跨地域架构既要保证数据不丢、服务不断,也要让不同区域的用户就近读写。Ceph RGW通过multisite机制实现这一目标,其核心设计围绕realm、zonegroup、zone三个逻辑层级展开,并依靠元数据同步与数据同步两条独立链路完成跨集群复制。理解同步游标、period发布和主备/双活模式的选择,是落地部署和后期运维的关键。多区部署不仅适用于跨机房容灾,也能支撑就近访问场景,但网络带宽、时钟同步、版本一致性等细节决定了系统的稳定性。本文结合完整的部署流程、

weixin_34396103的博客 296

Ceph MGR RGW 模块实战指南:用 ceph rgw realm/zone 命令一键编排多站点部署

本文围绕 Ceph Manager 守护进程内置的 `rgw` 模块展开,它是 RGW 多站点(multisite)部署的"一键编排入口":通过 `ceph rgw realm bootstrap`、`ceph rgw zone create` 等命令,即可在 cephadm 编排器之上自动完成 realm、zonegroup、zone 的引导创建,部署 RGW 守护进程并输出用于跨集群同步的 r

gitblog_00131的博客 153

Ceph RGW 多站点动态 Reshard 设计解析:基于布局代际(Generation)的独立分片治理

本文基于 Ceph 仓库中 [src/doc/rgw/multisite-reshard.md](https://link.gitcode.com/i/24cf974de9cb3af6431d26dd43af3365) 这一设计文档,系统梳理 RGW(RADOS Gateway)在多站点复制场景下的动态 Reshard 方案。核心思路是:**让每个 zone 独立决定桶的分片(shard)布局,同

gitblog_00926的博客 990

Ceph RGW对象存储完整教程:如何用S3 API构建私有云存储

Ceph RGW(Ceph Object Gateway,对象网关)是 Ceph 分布式存储平台提供的**对象存储接口**,它基于 `librados` 构建,对外暴露兼容 **Amazon S3 RESTful API** 和 **OpenStack Swift API** 的 HTTP 网关,让你无需依赖公有云,就能在私有环境里快速搭建一套完整的云存储系统。本教程面向新手,带你从零理解 RGW

gitblog_01111的博客 461

Rook Ceph Cluster Helm Chart 实战指南:用 Helm 编排与配置 Ceph 存储集群

本指南系统讲解 Rook 官方提供的 `rook-ceph-cluster` Helm Chart:它是对 Rook 模板资源的轻量封装,能通过 `values.yaml` 一次性创建 CephCluster、CephBlockPool、CephFileSystem、CephObjectStore 等 CR 及配套 StorageClass、Ingress 与 Toolbox。读完本文,你将掌握从

gitblog_00706的博客 760

Ceph RGW 多站点(Multi-site)测试框架实战指南:本地多集群环境的搭建、测试运行与用例编写

本指南围绕 Ceph 对象网关(RGW)多站点复制功能的自动化测试框架展开,该框架允许开发者在一台机器上通过脚本搭建**本地的多集群(多 zone)环境**,并基于 nose 测试框架运行针对多站点同步、版本化对象、桶策略、数据日志等场景的测试用例。读完本文,你将掌握该框架的入口与运行方式、配置文件的全部参数语义、底层环境搭建流程(mstart.sh/mrgw.sh 驱动的 realm/perio

gitblog_00144的博客 217

Ceph RGW 桶日志(Bucket Logging)完全指南:配置、日志格式与运维实践

> 本文基于 Ceph 开源仓库(Tentacle 版本引入)的 `doc/radosgw/bucket_logging.rst` 文档,结合 `src/rgw` 下的源码实现([rgw_bucket_logging.h](https://link.gitcode.com/i/fe3288361c23815dba1f13138e885252)、[rgw_bucket_logging.cc](htt

gitblog_00974的博客 638

Ceph RGW Admin Operations API 完整指南:用户、账户、桶、配额、限流与去重管理

本文以 Ceph 官方仓库 [doc/radosgw/adminops.rst](https://link.gitcode.com/i/c970c32fe60ced36bff7fba615988fb3) 为主体,系统讲解 Ceph RADOS Gateway(RGW)内置的 Admin Operations RESTful API——一套用于集群信息查询、用户/账户/子用户/密钥管理、桶与对象运维

gitblog_01027的博客 953
上一篇: Ceph RGW远程同步(multisite)配置
下一篇: Ceph BackoffThrottle分析
for_tech
博客等级 码龄11年 50粉丝 37原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值