Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Region properties middle key #3260

Merged
merged 21 commits into from
Jul 6, 2018
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
440e914
Add `default_cf_middle_key` and `write_cf_middle_key` into
hicqu Jun 29, 2018
c112589
Add `default_cf_middle_key` and `write_cf_middle_key` into
hicqu Jun 29, 2018
9444a4d
Merge branch 'region-properties-middle-key' of github.com:hicqu/tikv …
hicqu Jun 29, 2018
f611108
Merge branch 'master' into region-properties-middle-key
hicqu Jun 29, 2018
4dae77f
fix.
hicqu Jun 29, 2018
d5f2424
Merge branch 'master' into region-properties-middle-key
hicqu Jul 2, 2018
a387eae
Merge branch 'master' into region-properties-middle-key
hicqu Jul 2, 2018
4a17879
use latest kvproto.
hicqu Jul 2, 2018
06c4de0
Merge branch 'region-properties-middle-key' of github.com:hicqu/tikv …
hicqu Jul 2, 2018
f40e62d
Merge branch 'master' into region-properties-middle-key
hicqu Jul 3, 2018
8390b63
fix.
hicqu Jul 3, 2018
6bd7fc7
address comments.
hicqu Jul 3, 2018
cf62bce
Merge branch 'master' into region-properties-middle-key
hicqu Jul 3, 2018
2ce9760
Merge branch 'master' into region-properties-middle-key
hicqu Jul 3, 2018
98f88cb
Merge branch 'master' into region-properties-middle-key
hicqu Jul 4, 2018
7909302
Merge branch 'master' into region-properties-middle-key
huachaohuang Jul 4, 2018
5018993
Merge branch 'master' into region-properties-middle-key
zhangjinpeng87 Jul 5, 2018
0705f71
Merge branch 'master' into region-properties-middle-key
hicqu Jul 5, 2018
ebfe622
address comments.
hicqu Jul 5, 2018
42aa8f5
Merge branch 'master' into region-properties-middle-key
hicqu Jul 6, 2018
ad6b66b
address comments.
hicqu Jul 6, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 72 additions & 2 deletions src/raftstore/store/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::Bound::Excluded;
use std::option::Option;
use std::{fmt, u64};

Expand Down Expand Up @@ -326,6 +327,37 @@ pub fn get_region_approximate_size_cf(
Ok(size)
}

/// Get the approxmiate middle key of the region. The returned key maybe
/// is timpstamped if transaction KV is used, and must start with "z".
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/timpstamped/timestamped

pub fn get_region_approximate_middle_cf(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we point out what does middle means?

db: &DB,
cfname: &str,
region: &metapb::Region,
) -> Result<Option<Vec<u8>>> {
let cf = rocksdb_util::get_cf_handle(db, cfname)?;
let start = keys::enc_start_key(region);
let end = keys::enc_end_key(region);
let range = Range::new(&start, &end);
let collection = db.get_properties_of_tables_in_range(cf, &[range])?;

let mut keys = Vec::new();
for (_, v) in &*collection {
let props = SizeProperties::decode(v.user_collected_properties())?;
keys.extend(
props
.index_handles
.range::<[u8], _>((Excluded(start.as_slice()), Excluded(end.as_slice())))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why both are excluded?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The middle key is supposed to be used for split regions. So we don't hope the key equals to region's start key or end key.

.map(|(k, _)| k.to_owned()),
);
}
keys.sort();
if keys.is_empty() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should sort these keys here.

return Ok(None);
}
let middle = (keys.len() - 1) / 2;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why sub 1?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it, but maybe we could add a comment here? @hicqu

Ok(Some(keys.swap_remove(middle)))
}

pub fn get_region_approximate_size(db: &DB, region: &metapb::Region) -> Result<u64> {
let mut size = 0;
for cfname in LARGE_CFS {
Expand Down Expand Up @@ -544,8 +576,7 @@ pub fn conf_state_from_region(region: &metapb::Region) -> ConfState {

#[cfg(test)]
mod tests {
use std::process;
use std::thread;
use std::{iter, process, thread};

use kvproto::metapb::{self, RegionEpoch};
use kvproto::raft_cmdpb::AdminRequest;
Expand All @@ -558,6 +589,7 @@ mod tests {
use raftstore::store::peer_storage;
use storage::mvcc::{Write, WriteType};
use storage::{Key, ALL_CFS, CF_DEFAULT};
use util::escape;
use util::properties::{MvccPropertiesCollectorFactory, SizePropertiesCollectorFactory};
use util::rocksdb::{get_cf_handle, new_engine_opt, CFOptions};
use util::time::{monotonic_now, monotonic_raw_now};
Expand Down Expand Up @@ -1174,4 +1206,42 @@ mod tests {
check_region_epoch(&req, &region, true).unwrap_err();
}
}

#[test]
fn test_get_region_approximate_middle_cf() {
let tmp = TempDir::new("test_raftstore_util").unwrap();
let path = tmp.path().to_str().unwrap();

let db_opts = DBOptions::new();
let mut cf_opts = ColumnFamilyOptions::new();
cf_opts.set_level_zero_file_num_compaction_trigger(10);
let f = Box::new(SizePropertiesCollectorFactory::default());
cf_opts.add_table_properties_collector_factory("tikv.size-collector", f);
let cfs_opts = LARGE_CFS
.iter()
.map(|cf| CFOptions::new(cf, cf_opts.clone()))
.collect();
let engine = rocksdb_util::new_engine_opt(path, db_opts, cfs_opts).unwrap();

let cf_handle = engine.cf_handle(CF_DEFAULT).unwrap();
let mut big_value = Vec::with_capacity(256);
big_value.extend(iter::repeat(b'v').take(256));
for i in 0..100 {
let k = format!("key_{:03}", i).into_bytes();
let k = keys::data_key(Key::from_raw(&k).encoded());
engine.put_cf(cf_handle, &k, &big_value).unwrap();
// Flush for every key so that we can know the exact middle key.
engine.flush_cf(cf_handle, true).unwrap();
}

let region = make_region(1, vec![], vec![]);
let middle_key = get_region_approximate_middle_cf(&engine, CF_DEFAULT, &region)
.unwrap()
.unwrap();

let middle_key = Key::from_encoded(keys::origin_key(&middle_key).to_owned())
.raw()
.unwrap();
assert_eq!(escape(&middle_key), "key_049");
}
}
37 changes: 34 additions & 3 deletions src/server/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ use std::rc::Rc;
use std::str::FromStr;
use std::sync::Arc;
use std::{error, result};
use util::collections::HashSet;

use protobuf::{self, Message, RepeatedField};

use kvproto::debugpb::{DB as DBType, MODULE};
use kvproto::debugpb::{DB as DBType, *};
use kvproto::kvrpcpb::{MvccInfo, MvccLock, MvccValue, MvccWrite, Op};
use kvproto::metapb::Region;
use kvproto::raft_serverpb::*;
Expand All @@ -40,6 +39,8 @@ use raftstore::store::{keys, CacheQueryStats, Engines, Iterable, Peekable, PeerS
use storage::mvcc::{Lock, LockType, Write, WriteType};
use storage::types::{truncate_ts, Key};
use storage::{CF_DEFAULT, CF_LOCK, CF_RAFT, CF_WRITE};
use util::codec::bytes;
use util::collections::HashSet;
use util::config::ReadableSize;
use util::escape;
use util::properties::MvccProperties;
Expand Down Expand Up @@ -630,7 +631,33 @@ impl Debugger {
mvcc_properties.add(&mvcc);
}

let res = [
// Calculate region middle key based on default and write cf size.
// It's in encoded format, no timestamp padding and escaped to string.
let get_cf_size =
|cf: &str| raftstore_util::get_region_approximate_size_cf(db, cf, &region);

let default_cf_size = box_try!(get_cf_size(CF_DEFAULT));
let write_cf_size = box_try!(get_cf_size(CF_WRITE));

let middle_by_cf = if default_cf_size >= write_cf_size {
CF_DEFAULT
} else {
CF_WRITE
};

let middle_key = match box_try!(raftstore_util::get_region_approximate_middle_cf(
db,
middle_by_cf,
&region
)) {
Some(data_key) => {
let mut key = keys::origin_key(&data_key);
box_try!(bytes::decode_bytes(&mut key, false))
}
None => Vec::new(),
};

let mut res: Vec<(String, String)> = [
("num_files", collection.len() as u64),
("num_entries", num_entries),
("num_deletes", num_entries - mvcc_properties.num_versions),
Expand All @@ -643,6 +670,10 @@ impl Debugger {
].iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect();
res.push((
"middle_key_by_approximate_size".to_string(),
escape(&middle_key),
));
Ok(res)
}
}
Expand Down
6 changes: 2 additions & 4 deletions src/server/service/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,13 +382,11 @@ impl<T: RaftStoreRouter + 'static + Send> debugpb_grpc::Debug for Service<T> {
sink: UnarySink<GetRegionPropertiesResponse>,
) {
const TAG: &str = "get_region_properties";
let debugger = self.debugger.clone();

let f = self
.pool
.spawn(
future::ok(self.debugger.clone())
.and_then(move |debugger| debugger.get_region_properties(req.get_region_id())),
)
.spawn_fn(move || debugger.get_region_properties(req.get_region_id()))
.map(|props| {
let mut resp = GetRegionPropertiesResponse::new();
for (name, value) in props {
Expand Down