55
66#include " src/redis.h"
77#include < sstream>
8-
8+ #include < thread>
9+ #include < fstream>
10+ #include < glog/logging.h>
911namespace storage {
1012
1113Redis::Redis (Storage* const s, const DataType& type)
@@ -20,6 +22,7 @@ Redis::Redis(Storage* const s, const DataType& type)
2022 default_compact_range_options_.exclusive_manual_compaction = false ;
2123 default_compact_range_options_.change_level = true ;
2224 handles_.clear ();
25+ StartBigKeysLogThread ();
2326}
2427
2528Redis::~Redis () {
@@ -33,6 +36,7 @@ Redis::~Redis() {
3336 if (default_compact_range_options_.canceled ) {
3437 delete default_compact_range_options_.canceled ;
3538 }
39+ stop_big_keys_log_ = true ;
3640}
3741
3842Status Redis::GetScanStartPoint (const Slice& key, const Slice& pattern, int64_t cursor, std::string* start_point) {
@@ -109,7 +113,16 @@ Status Redis::SetOptions(const OptionType& option_type, const std::unordered_map
109113 }
110114 return s;
111115}
112-
116+ inline const char * DataTypeName (DataType type) {
117+ switch (type) {
118+ case kStrings : return " string" ;
119+ case kHashes : return " hash" ;
120+ case kLists : return " list" ;
121+ case kSets : return " set" ;
122+ case kZSets : return " zset" ;
123+ default : return " unknown" ;
124+ }
125+ }
113126void Redis::GetRocksDBInfo (std::string &info, const char *prefix) {
114127 std::ostringstream string_stream;
115128 string_stream << " #" << prefix << " RocksDB" << " \r\n " ;
@@ -198,5 +211,52 @@ void Redis::SetCompactRangeOptions(const bool is_canceled) {
198211 default_compact_range_options_.canceled ->store (is_canceled);
199212 }
200213}
201-
214+ // big keys
215+ void Redis::CheckAndRecordBigKeys (const std::string& key, DataType type, uint64_t key_size, uint64_t value_size) {
216+ bool is_bigkey = false ;
217+ if (type == kStrings ) {
218+ is_bigkey = (key_size >= BIGKEYS_THRESHOLD || value_size >= BIGKEYS_THRESHOLD);
219+ } else {
220+ is_bigkey = (key_size >= BIGKEYS_THRESHOLD);
221+ }
222+ if (is_bigkey) {
223+ std::lock_guard<std::mutex> lock (big_keys_mutex_);
224+ BigKeyInfo info;
225+ info.key = key;
226+ info.type = type;
227+ info.key_size = key_size;
228+ info.value_size = value_size;
229+ info.last_update_time = static_cast <uint64_t >(time (nullptr ));
230+ big_keys_info_map_[key] = info;
231+ }
232+ }
233+ void Redis::StartBigKeysLogThread () {
234+ std::thread ([this ]() {
235+ while (!stop_big_keys_log_) {
236+ {
237+ std::lock_guard<std::mutex> lock (big_keys_mutex_);
238+ std::ofstream ofs (" log/pika.WARNING" , std::ios::app);
239+ if (ofs.is_open ()) {
240+ auto now = std::chrono::system_clock::to_time_t (std::chrono::system_clock::now ());
241+ char time_buf[32 ];
242+ std::strftime (time_buf, sizeof (time_buf), " %Y-%m-%d %H:%M:%S" , std::localtime (&now));
243+ for (const auto & kv : big_keys_info_map_) {
244+ ofs << " [BigKey] key=" << kv.first
245+ << " type=" << DataTypeName (kv.second .type )
246+ << " key_size=" << kv.second .key_size ;
247+ if (kv.second .type == DataType::kStrings ) {
248+ ofs << " value_size=" << kv.second .value_size ;
249+ }
250+ ofs << " Updated Time=" << kv.second .last_update_time ;
251+ ofs << " Real time=" << time_buf << std::endl;
252+ }
253+ ofs.close ();
254+ } else {
255+ LOG (WARNING) << " Failed to open log/pika.WARNING for writing!" ;
256+ }
257+ }
258+ std::this_thread::sleep_for (std::chrono::minutes (1 ));
259+ }
260+ }).detach ();
261+ }
202262} // namespace storage
0 commit comments