Redis
 sql >> डेटाबेस >  >> NoSQL >> Redis

रेडिस में पाइपलाइन का उपयोग करते समय 100,000 रिकॉर्ड के साथ इतना धीमा क्यों है?

ऐसे बेंचमार्क (और विशेष रूप से JVM का उपयोग करने वाला बेंचमार्क) लिखने से पहले आपको कुछ बिंदुओं पर विचार करने की आवश्यकता है:

  • अधिकांश (भौतिक) मशीनों पर, जब पाइपलाइनिंग का उपयोग किया जाता है, तो Redis 100K से अधिक op/s को संसाधित करने में सक्षम होता है। आपका बेंचमार्क केवल 100K आइटम से संबंधित है, इसलिए यह सार्थक परिणाम देने के लिए पर्याप्त समय तक नहीं टिकता है। इसके अलावा, JIT के क्रमिक चरणों के शुरू होने का कोई समय नहीं है।

  • निरपेक्ष समय बहुत प्रासंगिक मीट्रिक नहीं है। बेंचमार्क को कम से कम 10 सेकंड तक चालू रखते हुए थ्रूपुट (यानी प्रति सेकंड ऑपरेशन की संख्या) प्रदर्शित करना एक बेहतर और अधिक स्थिर मीट्रिक होगा।

  • आपका आंतरिक लूप बहुत सारा कचरा उत्पन्न करता है। यदि आप Jedis+Redis को बेंचमार्क करने की योजना बना रहे हैं, तो आपको अपने स्वयं के प्रोग्राम का ओवरहेड कम रखना होगा।

  • क्योंकि आपने सब कुछ मुख्य फ़ंक्शन में परिभाषित किया है, आपका लूप जेआईटी द्वारा संकलित नहीं किया जाएगा (आपके द्वारा उपयोग किए जाने वाले जेवीएम के आधार पर)। केवल आंतरिक विधि कॉल हो सकती है। यदि आप चाहते हैं कि जेआईटी कुशल हो, तो अपने कोड को उन तरीकों में समाहित करना सुनिश्चित करें जिन्हें जेआईटी द्वारा संकलित किया जा सकता है।

  • वैकल्पिक रूप से, आप वास्तविक माप करने से पहले एक वार्म-अप चरण जोड़ना चाह सकते हैं ताकि नंगे हड्डी दुभाषिया के साथ पहले पुनरावृत्तियों को चलाने के ऊपरी हिस्से और स्वयं जेआईटी की लागत का लेखा-जोखा न किया जा सके।

अब, रेडिस पाइपलाइनिंग के संबंध में, आपकी पाइपलाइन बहुत लंबी है। पाइपलाइन में 100K कमांड का मतलब है कि रेडिस को कुछ भी भेजने से पहले जेडिस को 6 एमबी बफर बनाना होगा। इसका मतलब है कि सॉकेट बफ़र्स (क्लाइंट साइड पर, और शायद सर्वर-साइड पर) संतृप्त हो जाएंगे, और रेडिस को 6 एमबी संचार बफ़र्स से भी निपटना होगा।

इसके अलावा, आपका बेंचमार्क अभी भी सिंक्रोनस है (पाइपलाइन का उपयोग जादुई रूप से इसे एसिंक्रोनस नहीं बनाता है)। दूसरे शब्दों में, जब तक आपकी पाइपलाइन की अंतिम क्वेरी रेडिस को नहीं भेजी जाती, तब तक जेडिस उत्तर पढ़ना शुरू नहीं करेगा। जब पाइपलाइन बहुत लंबी होती है, तो उसमें चीजों को अवरुद्ध करने की क्षमता होती है।

पाइपलाइन के आकार को 100-1000 संचालन तक सीमित करने पर विचार करें। बेशक, यह अधिक राउंडट्रिप उत्पन्न करेगा, लेकिन संचार स्टैक पर दबाव एक स्वीकार्य स्तर तक कम हो जाएगा। उदाहरण के लिए, निम्नलिखित कार्यक्रम पर विचार करें:

import redis.clients.jedis.*;
import java.util.*;

public class TestPipeline {

    /**
     * @param args
     */

    int i = 0; 
    Map<String, String> map = new HashMap<String, String>();
    ShardedJedis jedis;  

    // Number of iterations
    // Use 1000 to test with the pipeline, 100 otherwise
    static final int N = 1000;

    public TestPipeline() {
      JedisShardInfo si = new JedisShardInfo("127.0.0.1", 6379);
      List<JedisShardInfo> list = new ArrayList<JedisShardInfo>();
      list.add(si);
      jedis = new ShardedJedis(list);
    } 

    public void push( int n ) {
     ShardedJedisPipeline pipeline = jedis.pipelined();
     for ( int k = 0; k < n; k++) {
      map.put("id", "" + i);
      map.put("name", "lyj" + i);
      pipeline.hmset("m" + i, map);
      ++i;
     }
     pipeline.sync(); 
    }

    public void push2( int n ) {
     for ( int k = 0; k < n; k++) {
      map.put("id", "" + i);
      map.put("name", "lyj" + i);
      jedis.hmset("m" + i, map);
      ++i;
     }
    }

    public static void main(String[] args) {
      TestPipeline obj = new TestPipeline();
      long startTime = System.currentTimeMillis();
      for ( int j=0; j<N; j++ ) {
       // Use push2 instead to test without pipeline
       obj.push(1000); 
       // Uncomment to see the acceleration
       //System.out.println(obj.i);
     }
     long endTime = System.currentTimeMillis();
     double d = 1000.0 * obj.i;
     d /= (double)(endTime - startTime);
     System.out.println("Throughput: "+d);
   }
 }

इस कार्यक्रम के साथ, आप पाइपलाइनिंग के साथ या उसके बिना परीक्षण कर सकते हैं। पाइपलाइनिंग का उपयोग करते समय पुनरावृत्तियों (एन पैरामीटर) की संख्या में वृद्धि करना सुनिश्चित करें, ताकि यह कम से कम 10 सेकंड तक चले। यदि आप लूप में प्रिंटलाइन को अनकम्मेंट करते हैं, तो आप महसूस करेंगे कि प्रोग्राम शुरुआत में धीमा है और जेआईटी चीजों को अनुकूलित करना शुरू कर देता है (इसीलिए प्रोग्राम को सार्थक परिणाम देने के लिए कम से कम कई सेकंड चलना चाहिए)।

मेरे हार्डवेयर (एक पुराना एथलॉन बॉक्स) पर, जब पाइपलाइन का उपयोग किया जाता है तो मैं 8-9 गुना अधिक थ्रूपुट प्राप्त कर सकता हूं। इनर लूप में की/वैल्यू फॉर्मेटिंग को ऑप्टिमाइज़ करके और वार्म-अप फेज़ जोड़कर प्रोग्राम को और बेहतर बनाया जा सकता है।




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. हार्ड विफलता के मामले में रेडिस क्लस्टर में किसी विशेष नोड के हैश स्लॉट को फिर से कैसे शुरू करें?

  2. रेडिस क्लाइंट

  3. गोलांग + रेडिस समवर्ती अनुसूचक प्रदर्शन मुद्दा

  4. क्या Stackexchange.Redis की आग और गारंटी वितरण को भूल जाता है?

  5. रेडिस का उपयोग करके अधिसूचना और समाचार क्षेत्र