রেডিস স্ট্রিং বনাম রেডিস হ্যাশগুলি JSON উপস্থাপনের জন্য: দক্ষতা?


287

আমি একটি জেএসএন পে-লোডকে রেডিসে সঞ্চয় করতে চাই। সত্যিই 2 টি উপায় আছে আমি এটি করতে পারি:

  1. একটি সাধারণ স্ট্রিং কী এবং মান ব্যবহার করে।
    কী: ব্যবহারকারী, মান: পেডলোড (পুরো জেএসএন ব্লব যা 100-200 কেবি হতে পারে)

    SET user:1 payload

  2. হ্যাশ ব্যবহার করে

    HSET user:1 username "someone"
    HSET user:1 location "NY"
    HSET user:1 bio "STRING WITH OVER 100 lines"

মনে রাখবেন যে আমি যদি হ্যাশ ব্যবহার করি তবে মান দৈর্ঘ্য অনুমানযোগ্য নয়। তারা উপরের জৈব উদাহরণের মতো সমস্ত সংক্ষিপ্ত নয়।

কোনটি আরও স্মৃতিশক্তি দক্ষ? স্ট্রিং কী এবং মানগুলি ব্যবহার করছেন, বা একটি হ্যাশ ব্যবহার করছেন?


37
এছাড়াও মনে রাখবেন যে আপনি কোনও হ্যাশ সেটে কোনও নেস্টেড জেএসওএন বস্তু (সহজেই) সঞ্চয় করতে পারবেন না।
জোনাটান হেডবার্গ

3
রেজসন এখানেও সহায়তা করতে পারে: redislabs.com/blog/redis-as-a-json-store
সিহান বি।

2
কেউ কি এখানে রেজন ব্যবহার করেছেন?
স্বামী

উত্তর:


168

আপনি কীভাবে ডেটা অ্যাক্সেস করেন তা নির্ভর করে:

বিকল্প 1 এ যান:

  • আপনি যদি আপনার অ্যাক্সেসের বেশিরভাগ ক্ষেত্র ব্যবহার করেন।
  • সম্ভাব্য কীগুলির মধ্যে বৈচিত্র থাকলে

বিকল্প 2 এর জন্য যান:

  • আপনি যদি আপনার বেশিরভাগ অ্যাক্সেসে কেবলমাত্র একক ক্ষেত্র ব্যবহার করেন।
  • আপনি যদি সর্বদা জানেন তবে কোন ক্ষেত্রগুলি উপলব্ধ

পিএস: থাম্বের নিয়ম হিসাবে, এমন বিকল্পের জন্য যান যা আপনার বেশিরভাগ ব্যবহারের ক্ষেত্রে কম প্রশ্নের প্রয়োজন।


28
বিকল্প 1 একটি ভাল ধারণা যদি না হয় সমবর্তী পরিমার্জন এর JSONপে লোড বলে আশা করা হচ্ছে (একটি ধ্রুপদী সমস্যা অ পারমাণবিক read-modify-write )।
সামভিন

1
জসন স্ট্রব হিসাবে বা রেডিসে বাইট অ্যারে হিসাবে জসন ব্লব সংরক্ষণের উপলভ্য বিকল্পগুলির মধ্যে কোনটি বেশি দক্ষ?
Vinit89

422

এই নিবন্ধটি এখানে প্রচুর অন্তর্দৃষ্টি প্রদান করতে পারে: http://redis.io/topics/mmory-optimization

রেডিসে অবজেক্টগুলির একটি অ্যারে সঞ্চয় করার জন্য অনেকগুলি উপায় রয়েছে ( স্পোলার : বেশিরভাগ ব্যবহারের ক্ষেত্রে আমি বিকল্প 1 পছন্দ করি):

  1. JSON- এনকোডেড স্ট্রিং হিসাবে সম্পূর্ণ অবজেক্টটিকে একটি একক কীতে সংরক্ষণ করুন এবং একটি সেট (বা আরও উপযুক্ত হলে তালিকা) তালিকা ব্যবহার করে সমস্ত অবজেক্টের উপর নজর রাখুন। উদাহরণ স্বরূপ:

    INCR id:users
    SET user:{id} '{"name":"Fred","age":25}'
    SADD users {id}

    সাধারণভাবে বলতে গেলে এটি বেশিরভাগ ক্ষেত্রে সম্ভবত সেরা পদ্ধতি। যদি অবজেক্টে অনেকগুলি ক্ষেত্র থাকে তবে আপনার অবজেক্টগুলি অন্য অবজেক্টগুলির সাথে বাসা বাঁধে না এবং আপনি একবারে কেবলমাত্র ক্ষেত্রের একটি ছোট উপসেট অ্যাক্সেস করার ঝোঁক রাখেন, বিকল্প 2 দিয়ে যাওয়ার চেয়ে ভাল।

    সুবিধা : একটি "ভাল অনুশীলন" হিসাবে বিবেচিত। প্রতিটি বস্তু একটি পূর্ণ-বিকাশযুক্ত রেডিস কী। জেএসএন পার্সিং দ্রুত হয়, বিশেষত যখন আপনাকে একবারে এই বিষয়টির জন্য অনেকগুলি ক্ষেত্র অ্যাক্সেস করতে হবে need অসুবিধাগুলি : ধীরে ধীরে যখন আপনার কেবল একটি একা ক্ষেত্র অ্যাক্সেস করতে হবে।

  2. প্রতিটি বস্তুর বৈশিষ্ট্য একটি রেডিস হ্যাশে সংরক্ষণ করুন।

    INCR id:users
    HMSET user:{id} name "Fred" age 25
    SADD users {id}

    সুবিধা : একটি "ভাল অনুশীলন" হিসাবে বিবেচিত। প্রতিটি বস্তু একটি পূর্ণ-বিকাশযুক্ত রেডিস কী। জেএসএন স্ট্রিং বিশ্লেষণ করার দরকার নেই। অসুবিধাগুলি : যখন আপনাকে কোনও অবজেক্টের সমস্ত / বেশিরভাগ ক্ষেত্র অ্যাক্সেস করার প্রয়োজন হয় তখন সম্ভবত ধীর হয়। এছাড়াও, নেস্টেড অবজেক্টস (অবজেক্টের মধ্যে থাকা অবজেক্টস) সহজে সংরক্ষণ করা যায় না।

  3. রেডিস হ্যাশে প্রতিটি বস্তুকে জেএসএন স্ট্রিং হিসাবে সংরক্ষণ করুন।

    INCR id:users
    HMSET users {id} '{"name":"Fred","age":25}'

    এটি আপনাকে কিছুটা সংহত করতে এবং প্রচুর কীগুলির পরিবর্তে দুটি কী ব্যবহার করতে সহায়তা করে। সুস্পষ্ট অসুবিধাটি হ'ল আপনি প্রতিটি ব্যবহারকারীর অবজেক্টে টিটিএল (এবং অন্যান্য স্টাফ) সেট করতে পারবেন না, কারণ এটি কেবল রেডিস হ্যাশের একটি ক্ষেত্র এবং সম্পূর্ণ বিকাশযুক্ত রেডিস কী নয়।

    সুবিধা : জেএসএন পার্সিং দ্রুত হয়, বিশেষত যখন আপনাকে একবারে এই বিষয়টির জন্য অনেকগুলি ক্ষেত্র অ্যাক্সেস করতে হবে। মূল কী নেমস্পেসের "দূষণকারী" কম। অসুবিধাগুলি : আপনার প্রচুর অবজেক্ট থাকে যখন # 1 হিসাবে একই মেমরির ব্যবহার সম্পর্কে। আপনার কেবলমাত্র একটি একক ক্ষেত্র অ্যাক্সেস করার প্রয়োজন হলে # 2 এর চেয়ে ধীরে ধীরে। সম্ভবত একটি "ভাল অনুশীলন" হিসাবে বিবেচনা করা হয় না।

  4. প্রতিটি বস্তুর প্রতিটি সম্পত্তি একটি উত্সর্গীকৃত কীতে সঞ্চয় করুন।

    INCR id:users
    SET user:{id}:name "Fred"
    SET user:{id}:age 25
    SADD users {id}

    উপরের নিবন্ধ অনুসারে, এই বিকল্পটি প্রায় কখনও পছন্দ করা হয় না (যদি না অবজেক্টের সম্পত্তিটির জন্য নির্দিষ্ট টিটিএল বা কিছু থাকে না)।

    সুবিধাগুলি : অবজেক্ট বৈশিষ্ট্যগুলি হ'ল রেডিস কীগুলি পূর্ণ-বিকাশযুক্ত, যা আপনার অ্যাপ্লিকেশনটির জন্য ওভারকিল নাও হতে পারে। অসুবিধাগুলি : ধীর, আরও মেমরি ব্যবহার করে এবং "সেরা অনুশীলন" হিসাবে বিবেচিত হয় না। মূল কী নেমস্পেসের প্রচুর দূষণকারী।

সংক্ষিপ্তসার

বিকল্প 4 সাধারণত পছন্দ করা হয় না। বিকল্প 1 এবং 2 খুব সমান এবং এগুলি উভয়ই সাধারণ। আমি বিকল্প 1 টি পছন্দ করি (সাধারণত বলছি) কারণ এটি আপনাকে আরও জটিল অবজেক্টগুলি সংরক্ষণ করতে দেয় (বাসা বাঁধার একাধিক স্তর সহ)) বিকল্প 3 ব্যবহার করা হয় যখন আপনি সত্যিকার অর্থে মূল কী নেমস্পেস দূষণ না করার বিষয়ে চিন্তা করেন (যেমন আপনি সেখানে চান না) আপনার ডাটাবেসে অনেকগুলি কী হতে হবে এবং আপনি টিটিএল, কী শার্পিং, বা যেকোন কিছুতে উদ্বিগ্ন হন না।

যদি আমি এখানে কিছু ভুল হয়ে থাকে তবে দয়া করে কোনও মন্তব্য রেখে বিবেচনা করুন এবং ডাউনভোটিংয়ের আগে আমাকে উত্তরটি সংশোধন করার অনুমতি দিন। ধন্যবাদ! :)


4
বিকল্প # 2 এর জন্য আপনি "যখন কোনও অবজেক্টের সমস্ত / বেশিরভাগ ক্ষেত্রের অ্যাক্সেসের প্রয়োজন হয় তখন সম্ভবত" ধীরে ধীরে ধীরে ধীরে কথা বলবেন। এটি পরীক্ষা করা হয়েছে?
মাইকগ্রাইলিং

4
hmget জন্য O (ঢ) হয় এন ক্ষেত্র পেতে বিকল্প 1 সাথে এখনও হে (1) হবে। তাত্ত্বিকভাবে, হ্যাঁ, এটি দ্রুত।
অরুনা হেরাথ

4
1 এবং 2 বিকল্পগুলি হ্যাশের সাথে সংযুক্ত করার বিষয়ে কীভাবে? প্রায়শই আপডেট হওয়া ডেটার জন্য বিকল্প বিকল্প 1 এবং প্রায়শই আপডেট হওয়া ডেটার জন্য বিকল্প 2 ব্যবহার করবেন? বলুন, আমরা নিবন্ধগুলি সংরক্ষণ করছি এবং আমরা জেএসএন স্ট্রিংয়ে শিরোনাম, লেখক এবং url এর মতো objক্ষেত্রগুলি জেনেরিক কী যুক্ত করে দেখি, মতামত, ভোট এবং পৃথক কী সহ ভোটারদের মতো ক্ষেত্রগুলি সঞ্চয় করি? একটি একক READ ক্যোয়ারির সাথে আপনি পুরো অবজেক্টটি পাবেন এবং এখনও আপনার অবজেক্টের গতিশীল অংশগুলি দ্রুত আপডেট করতে পারবেন? JSON স্ট্রিংয়ের ক্ষেত্রগুলিতে অপেক্ষাকৃত বিরল আপডেটগুলি লেনদেনে পুরো অবজেক্টটি পড়ে এবং লেখার মাধ্যমে করা যেতে পারে।
অরুন

2
এর মতে: ( ইনস্টাগ্রাম-engineering.tumblr.com/post/12202313862/… ) এটি মেমরির ব্যবহারের ক্ষেত্রে একাধিক হ্যাশগুলিতে সঞ্চয় করার পরামর্শ দেওয়া হয়। অরুনের অপ্টিমাইজেশনের পরে, আমরা এটি করতে পারি: 1- খুব বেশি আপডেট হওয়া ডেটার জন্য স্ট্রিং হিসাবে
জসন পেডলোডকে

2
বিকল্প 1 এর ক্ষেত্রে, আমরা কেন এটি একটি সেট যুক্ত করছি? কেন আমরা সহজভাবে আদেশটি ব্যবহার করতে পারি না এবং কীভাবে ফিরে আসে তা পরীক্ষা করতে পারি না।
প্রাগমেটিক

8

প্রদত্ত উত্তরের একটি সেটটিতে কিছু সংযোজন:

সবার আগে আপনি যদি রেডিস হ্যাশকে দক্ষতার সাথে ব্যবহার করতে চান তবে আপনাকে অবশ্যই একটি কী গণনা সর্বোচ্চ নম্বর এবং সর্বাধিক আকারের মানগুলি জানতে হবে - অন্যথায় যদি তারা হ্যাশ-সর্বোচ্চ-জিপলিস্ট-মান বা হ্যাশ-ম্যাক্স-জিপলিস্ট-এন্ট্রিগুলি ছড়িয়ে দেয় তবে রেডিস এটিকে ব্যবহারিকভাবে রূপান্তরিত করবে একটি হুডের নীচে সাধারণ কী / মান জোড়া। (হ্যাশ-সর্বোচ্চ-জিপলিস্ট-মান, হ্যাশ-ম্যাক্স-জিপলিস্ট-এন্ট্রি দেখুন) এবং একটি হ্যাশ বিকল্পগুলির থেকে একটি ফণা ভেঙে দেওয়া আসলেই খারাপ, কারণ রেডিসের অভ্যন্তরে প্রতিটি সাধারণ কী / মান জুটি প্রতি জোড়া +90 বাইট ব্যবহার করে।

এর অর্থ হ'ল আপনি যদি বিকল্প দুটি দিয়ে শুরু করেন এবং দুর্ঘটনাক্রমে সর্বাধিক হ্যাশ-জিপলিস্ট-মানটি ভেঙে যান তবে আপনি প্রতিটি মডেলটিতে 9090 বাইট পাবেন যা আপনার ব্যবহারকারীর মডেলের অভ্যন্তরে রয়েছে! (আসলে +90 নয় তবে +70 নীচে কনসোল আউটপুট দেখুন)

 # you need me-redis and awesome-print gems to run exact code
 redis = Redis.include(MeRedis).configure( hash_max_ziplist_value: 64, hash_max_ziplist_entries: 512 ).new 
  => #<Redis client v4.0.1 for redis://127.0.0.1:6379/0> 
 > redis.flushdb
  => "OK" 
 > ap redis.info(:memory)
    {
                "used_memory" => "529512",
          **"used_memory_human" => "517.10K"**,
            ....
    }
  => nil 
 # me_set( 't:i' ... ) same as hset( 't:i/512', i % 512 ... )    
 # txt is some english fictionary book around 56K length, 
 # so we just take some random 63-symbols string from it 
 > redis.pipelined{ 10000.times{ |i| redis.me_set( "t:#{i}", txt[rand(50000), 63] ) } }; :done
 => :done 
 > ap redis.info(:memory)
  {
               "used_memory" => "1251944",
         **"used_memory_human" => "1.19M"**, # ~ 72b per key/value
            .....
  }
  > redis.flushdb
  => "OK" 
  # setting **only one value** +1 byte per hash of 512 values equal to set them all +1 byte 
  > redis.pipelined{ 10000.times{ |i| redis.me_set( "t:#{i}", txt[rand(50000), i % 512 == 0 ? 65 : 63] ) } }; :done 
  > ap redis.info(:memory)
   {
               "used_memory" => "1876064",
         "used_memory_human" => "1.79M",   # ~ 134 bytes per pair  
          ....
   }
    redis.pipelined{ 10000.times{ |i| redis.set( "t:#{i}", txt[rand(50000), 65] ) } };
    ap redis.info(:memory)
    {
             "used_memory" => "2262312",
          "used_memory_human" => "2.16M", #~155 byte per pair i.e. +90 bytes    
           ....
    }

দি হিপ্পো উত্তরের জন্য, অপশন একের মন্তব্যগুলি বিভ্রান্তিকর:

আপনার সমস্ত ক্ষেত্র বা একাধিক গেইট / সেট অপারেশন প্রয়োজন হলে উদ্ধার করতে hgetall / hmset / hmget

বিমিনিয়ার উত্তরের জন্য।

তৃতীয় বিকল্পটি আসলেই মজাদার, সর্বোচ্চ (আইডি) সহ ডেটাসেটের জন্য <হ'ল-ম্যাক্স-জিপলিস্ট-ভ্যালুতে এই সমাধানটিতে ও (এন) জটিলতা রয়েছে, কারণ আশ্চর্য, রেড্ডিস ছোট হ্যাশগুলিকে দৈর্ঘ্যের / কী / মানের অ্যারের মতো ধারক হিসাবে সংরক্ষণ করে store বস্তু!

তবে অনেক সময় হ্যাশগুলিতে কয়েকটি ক্ষেত্র থাকে। যখন হ্যাশগুলি ছোট হয় আমরা পরিবর্তে ওটিকে (এন) ডেটা স্ট্রাকচারে এনকোড করতে পারি, যেমন দৈর্ঘ্য-উপসর্গযুক্ত কী মান জোড়গুলির সাথে লিনিয়ার অ্যারের মতো। যেহেতু আমরা এটি কেবলমাত্র ছোট যখনই করি, তাই এইচজিইটি এবং এইচএসইটি কমান্ডের আনুপাতিক সময় এখনও ও (1) থাকে: হ্যাশটি এতে উপস্থিত উপাদানগুলির সংখ্যা বাড়ার সাথে সাথে একটি আসল হ্যাশ টেবিলে রূপান্তরিত হবে it

তবে আপনার চিন্তা করা উচিত নয়, আপনি হ্যাশ-সর্বাধিক জিপলিস্ট-এন্ট্রিগুলি খুব দ্রুত ভেঙে ফেলবেন এবং সেখানে গিয়ে আপনি এখন 1 নম্বর সমাধানে রয়েছেন।

দ্বিতীয় বিকল্পটি সম্ভবত হুডের নীচে চতুর্থ সমাধানে যাবে কারণ প্রশ্ন হিসাবে বলা হয়েছে:

মনে রাখবেন যে আমি যদি হ্যাশ ব্যবহার করি তবে মান দৈর্ঘ্য অনুমানযোগ্য নয়। তারা উপরের জৈব উদাহরণের মতো সমস্ত সংক্ষিপ্ত নয়।

এবং যেমনটি আপনি ইতিমধ্যে বলেছেন: চতুর্থ সমাধান হ'ল নিশ্চিতভাবে প্রতিটি বৈশিষ্ট্য অনুসারে +70 বাইট +

এই জাতীয় ডেটাসেট কীভাবে অনুকূল করা যায় সে সম্পর্কে আমার পরামর্শ:

আপনার কাছে দুটি বিকল্প রয়েছে:

  1. আপনি যদি প্রথম সমাধানের চেয়ে কিছু ব্যবহারকারীর বৈশিষ্ট্যের সর্বাধিক আকারের গ্যারান্টি দিতে না পারেন এবং মেমরির বিষয়টি যদি রেডিসে স্টোর করার আগে ব্যবহারকারী জসনকে কমপ্রেস করার চেয়ে গুরুত্বপূর্ণ।

  2. আপনি যদি সমস্ত বৈশিষ্ট্যের সর্বাধিক আকার জোর করতে পারেন। আপনি হ্যাশ-সর্বাধিক জিপলিস্ট-এন্ট্রি / মান সেট করতে পারবেন এবং ব্যবহারকারীর উপস্থাপনায় প্রতিটি হ্যাশ হিসাবে বা রেডিস গাইডের এই বিষয় থেকে হ্যাশ মেমরি অপ্টিমাইজেশন হিসাবে হ্যাশগুলি ব্যবহার করতে পারবেন: https://redis.io/topics/memory-optimization এবং স্টোর ব্যবহারকারী হিসাবে জসন স্ট্রিং। যে কোনও উপায়ে আপনি দীর্ঘ ব্যবহারকারীর বৈশিষ্ট্যগুলিও সংকুচিত করতে পারেন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.