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

रेडिस सॉर्ट किए गए सेट और यूआईडी स्टोर करने का सबसे अच्छा तरीका

मेरा पहला बिंदु यह नोट करना होगा कि 4 जीबी 20M सॉर्ट किए गए सेट को स्टोर करने के लिए तंग हैं। एक त्वरित प्रयास से पता चलता है कि 20M उपयोगकर्ता, उनमें से प्रत्येक 20 टैग के साथ 64 बिट बॉक्स पर लगभग 8 जीबी लेगा (और यह रेडिस 2.4 के साथ प्रदान किए गए सॉर्ट किए गए सेट ज़िपलिस्ट मेमोरी ऑप्टिमाइज़ेशन के लिए जिम्मेदार है - इसे पहले के संस्करणों के साथ भी कोशिश न करें) ।

सॉर्ट किए गए सेट आपके उपयोग के मामले का समर्थन करने के लिए आदर्श डेटा संरचना हैं। मैं उनका ठीक वैसे ही उपयोग करूंगा जैसा आपने वर्णन किया है।

जैसा कि आपने बताया, KEYS का उपयोग कुंजियों पर पुनरावृति करने के लिए नहीं किया जा सकता है। यह बल्कि डिबग कमांड के रूप में है। कुंजी पुनरावृत्ति का समर्थन करने के लिए, आपको यह एक्सेस पथ प्रदान करने के लिए डेटा संरचना जोड़ने की आवश्यकता है। रेडिस में एकमात्र संरचना जो पुनरावृत्ति का समर्थन कर सकती है वह सूची और क्रमबद्ध सेट (श्रेणी विधियों के माध्यम से) है। हालांकि, वे O(n) पुनरावृत्ति एल्गोरिदम को O(n^2) (सूची के लिए), या O(nlogn) (zset के लिए) में बदलने की प्रवृत्ति रखते हैं। कुंजियों को संग्रहीत करने के लिए एक सूची भी एक खराब विकल्प है क्योंकि इसे बनाए रखना मुश्किल होगा क्योंकि कुंजियाँ जोड़ी / हटाई जाती हैं।

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

तो उपयोगकर्ता पर पुनरावृत्ति का समर्थन करने के लिए:1000, उपयोगकर्ता:2000 और उपयोगकर्ता:1001, आइए एक मॉड्यूलो 1000 फ़ंक्शन चुनें। उपयोगकर्ता:1000 और उपयोगकर्ता:2000 को बकेट इंडेक्स में रखा जाएगा:0 जबकि उपयोगकर्ता:1001 को बकेट इंडेक्स में रखा जाएगा:1.

तो zsets के शीर्ष पर, अब हमारे पास निम्नलिखित कुंजियाँ हैं:

index:0 => set[ 1000, 2000 ]
index:1 => set[ 1001 ]

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

वैश्विक पुनरावृत्ति में 0 से 1000 (बहिष्कृत) की बाल्टियों पर एक साधारण लूप होता है। प्रत्येक बकेट के लिए, संबंधित सेट को पुनः प्राप्त करने के लिए SMEMBERS कमांड लागू किया जाता है, और क्लाइंट फिर अलग-अलग आइटम पर पुनरावृति कर सकता है।

यहाँ पायथन में एक उदाहरण दिया गया है:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ----------------------------------------------------

import redis, random

POOL = redis.ConnectionPool(host='localhost', port=6379, db=0)

NUSERS = 10000
NTAGS = 500
NBUCKETS = 1000

# ----------------------------------------------------
# Fill redis with some random data

def fill(r):
  p = r.pipeline()
  # Create only 10000 users for this example
  for id in range(0,NUSERS):
    user = "user:%d" % id
    # Add the user in the index: a simple modulo is used to hash the user id
    # and put it in the correct bucket
    p.sadd( "index:%d" % (id%NBUCKETS), id )
    # Add random tags to the user
    for x in range(0,20):
      tag = "tag:%d" % (random.randint(0,NTAGS))
      p.zincrby( user, tag, 1 )
    # Flush the pipeline every 1000 users
    if id % 1000 == 0:
      p.execute()
      print id
  # Flush one last time
  p.execute()

# ----------------------------------------------------
# Iterate on all the users and display their 5 highest ranked tags

def iterate(r):
  # Iterate on the buckets of the key index
  # The range depends on the function used to hash the user id
  for x in range(0,NBUCKETS):
    # Iterate on the users in this bucket
    for id in r.smembers( "index:%d"%(x) ):
      user = "user:%d" % int(id)
      print user,r.zrevrangebyscore(user,"+inf","-inf", 0, 5, True )

# ----------------------------------------------------
# Main function

def main():
  r = redis.Redis(connection_pool=POOL)
  r.flushall()
  m = r.info()["used_memory"]
  fill(r)
  info = r.info()
  print "Keys: ",info["db0"]["keys"]
  print "Memory: ",info["used_memory"]-m
  iterate(r)

# ----------------------------------------------------

main()

स्थिरांक में बदलाव करके, आप इस प्रोग्राम का उपयोग इस डेटा संरचना की वैश्विक मेमोरी खपत का मूल्यांकन करने के लिए भी कर सकते हैं।

आईएमओ यह रणनीति सरल और कुशल है, क्योंकि यह उपयोगकर्ताओं को जोड़ने/निकालने के लिए ओ (1) जटिलता प्रदान करती है, और सभी वस्तुओं पर पुनरावृति करने के लिए सही ओ (एन) जटिलता प्रदान करती है। केवल नकारात्मक पक्ष यह है कि कुंजी पुनरावृत्ति क्रम यादृच्छिक है।




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. क्या मुझे प्रत्येक कनेक्शन के लिए एक नया रेडिस क्लाइंट बनाना चाहिए?

  2. स्प्रिंग-डेटा-रेडिस 1.7.0.M1 का उपयोग करते समय रेडिस-क्लस्टर को कैसे कॉन्फ़िगर करें?

  3. रेडिस:सहेजने के लिए .rdb खोलने में विफल:अनुमति अस्वीकृत

  4. स्प्रिंग सेशन डेटा रेडिस - रेडिस स्टोर से वैध सत्र, वर्तमान उपयोगकर्ता प्राप्त करें

  5. त्रुटि:रेडिस पर रेडिस से कनेक्ट नहीं हो सका:6379:नाम या सेवा ज्ञात नहीं है