आईटी परियोजनाओं के लिए डेटा वेयरहाउस के रूप में टेलीग्राम

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

पूरा प्रोजेक्ट जीथब पर पोस्ट किया गया है, लिंक लेख के अंत में होगा।

छवि

मुख्य समस्या है


प्रारंभ में, मैं खुद के लिए एक साधारण टेलीग्राम बॉट कैलोरी काउंटर लिखना चाहता था, जो उपयोगकर्ता से एक नंबर प्राप्त करता है और वापस लौटता है कि दिन में कितनी कैलोरी सामान्य के लिए छोड़ दी जाती है। यही है, आपको प्रत्येक उपयोगकर्ता के लिए मोटे तौर पर कुछ चर संग्रहित करने की आवश्यकता है।

अंत में, आपको इस डेटा को संग्रहीत करने का एक तरीका चुनना था।

  1. विकल्प - वैश्विक चर , यादृच्छिक अभिगम स्मृति। विकल्प तुरंत विफलता है, क्योंकि जब प्रोग्राम क्रैश हो जाता है, तो हम सब कुछ खो देते हैं
  2. विकल्प - डिस्क पर एक फ़ाइल पर लिखें । यह इस तरह की परियोजना के लिए काम कर सकता है, लेकिन मैंने हरको पर एक बॉट को तैनात करने की योजना बनाई है, जो हर दिन डिस्क से सभी डेटा मिटा देता है। इसलिए यह विकल्प फिट नहीं हुआ
  3. विकल्प - Google स्प्रेडशीट । प्रारंभ में, मैं इस विकल्प पर ध्यान केन्द्रित करना चाहता था, लेकिन मुझे यह समझ में आने लगा कि टेबल पर प्रश्नों की संख्या की सीमा है, और केवल टेबल का उपयोग शुरू करने के लिए, आपको कोड की पंक्तियों को लिखना होगा और उनकी सरल-सरल एपीआई का पता लगाना होगा।
  4. विकल्प एक डेटाबेस है । हां, यह हर चीज में सबसे अच्छा विकल्प है। लेकिन इस तरह की परियोजना के लिए, यह उपयोग करने के लिए और भी मज़ेदार है। इसके अलावा, एक तृतीय-पक्ष सर्वर पर एक डेटाबेस की तैनाती और समर्थन के लिए एक बहुत पैसा खर्च होगा।

परिणामस्वरूप, इनमें से कोई भी विकल्प सामने नहीं आया। बेशक, दर्जनों अन्य तरीके हैं, लेकिन मैं चाहूंगा कि यह स्वतंत्र, तेज और न्यूनतम कोड के साथ हो।

निर्णय


यह विचार बहुत सरल है, डेटा स्टोरेज के लिए हम मेमोरी में साइक्लाइट डेटाबेस का उपयोग करेंगे, क्योंकि यह पहले से ही अजगर 3 में बनाया गया है और हम प्रोग्राम की प्रक्रिया बंद होने पर टेलीग्राम सर्वर पर एक छोटे अंतराल (लगभग हर 30 सेकंड) और बैकअप के साथ अपनी टेबल का बैकअप लेंगे।

यदि सर्वर क्रैश हो जाता है, तो पहले अनुरोध पर हम टेलीग्राम सर्वर से अपने टेबल को स्वचालित रूप से डाउनलोड करेंगे और डेटा को साइक्लाइट में पुनर्स्थापित करेंगे।

आप जैसे चाहें मेमोरी डेटाबेस में किसी अन्य का उपयोग कर सकते हैं।

आकर्षण आते हैं


  1. प्रदर्शन - मुख्य मेमोरी में डेटा के साथ काम करने के कारण, थर्ड-पार्टी सर्वर पर डेटाबेस का उपयोग करते समय प्रोग्राम निष्पादन की गति और भी तेज होती है (निष्पादन और परीक्षण की गति के ग्राफ अंत में होंगे)
  2. फ्री - डेटाबेस के लिए तीसरे पक्ष के सर्वर खरीदने की कोई आवश्यकता नहीं है और सभी डेटा टेलीग्राम सर्वर पर मुफ्त में बैकअप के रूप में संग्रहीत किया जाता है
  3. अपेक्षाकृत विश्वसनीय - यदि सर्वर अज्ञात कारणों से दुर्घटनाग्रस्त हो जाता है, तो हम पिछले 30 सेकंड (बैकअप अंतराल समय) के लिए अधिकतम डेटा खो देते हैं, एक कार्यशील प्रोटोटाइप या एक छोटी परियोजना के लिए यह पर्याप्त होगा।
  4. एक नियमित डेटाबेस पर स्विच करते समय न्यूनतम लागत - आपको कनेक्शन डेटा को बदलने, बैकअप कोड को हटाने और बैकअप से टेबल डेटा को एक नए डेटाबेस में स्थानांतरित करने की आवश्यकता है।

विपक्ष


  1. क्षैतिज स्केलिंग का अभाव
  2. आपको टेलीग्राम में दो खाते चाहिए (एक व्यवस्थापक के लिए, दूसरा उपयोगकर्ता के परीक्षण के लिए)
  3. रूस में ताले के कारण सर्वर काम नहीं करेगा
  4. टिप्पणियों में, मुझे लगता है कि आपको एक दर्जन अन्य बारीकियां मिलेंगी।

चुदने का समय


आइए एक साधारण क्लिकर लिखें और गति के लिए परीक्षण चलाएं।

एप्टी टेलीग्राम aiogram के साथ बातचीत के एक अतुल्यकालिक पुस्तकालय का उपयोग करते हुए बॉट को अजगर प्रोग्रामिंग भाषा में लिखा जाएगा।

सबसे पहले, आपको बॉट सेटिंग्स भरने की जरूरत है, मैं आपको यह नहीं बताता कि कैसे बोटफादर से टोकन प्राप्त करना है, इस विषय पर पहले से ही सैकड़ों लेख हैं।

हमें व्यवस्थापक के लिए एक टेलीग्राम में दूसरे खाते की भी आवश्यकता है, जिसमें हमारे बैकअप सहेजे जाएंगे।

Admin_id और config_id प्राप्त करने के लिए, हमें व्यवस्थापक खाते से बॉट शुरू करना होगा और बॉट को "admin" लिखना होगा, जिसके बाद यह पहला बैकअप बनाएगा और आपका admin_id, config_id लिखेगा। बदलें और बॉट को फिर से शुरू करें।

#-------------------- ------------------------- #    BotFather TOKEN = '1234567:your_token' #  logging.basicConfig(level=logging.INFO) bot = Bot(token=TOKEN) dp = Dispatcher(bot) #             admin_id=12345678 config_id=12345 conn = sqlite3.connect(":memory:") #  in memory  cursor = conn.cursor() 

तो अब चलो बॉट के मुख्य तर्क के माध्यम से चलते हैं


यदि बॉट को "व्यवस्थापक" शब्द के साथ एक संदेश मिलता है, तो हम निम्नलिखित डेटा मॉडल के साथ एक उपयोगकर्ता तालिका बनाते हैं:

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

एक परीक्षण उपयोगकर्ता जोड़ें, और हमारी तालिका के साथ टेलीग्राम सर्वर पर दस्तावेज़ भेजें। हम संदेश के रूप में admin_id और config_id को भी व्यवस्थापक को भेजते हैं। आईडी प्राप्त करने के बाद, इस कोड को टिप्पणी करने की आवश्यकता है।

 #    if message.text == 'admin': cursor.execute("CREATE TABLE users (chatid INTEGER , name TEXT, click INTEGER, state INTEGER)") cursor.execute("INSERT INTO users VALUES (1234, 'eee', 1,0)") conn.commit() sql = "SELECT * FROM users " cursor.execute(sql) data = cursor.fetchall() str_data = json.dumps(data) await bot.send_document(message.chat.id, io.StringIO(str_data)) await bot.send_message(message.chat.id, 'admin_id = {}'.format(message.chat.id)) await bot.send_message(message.chat.id, 'config_id = {}'.format(message.message_id+1)) 

उपयोगकर्ता तर्क


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

 #    try: sql = "SELECT * FROM users where chatid={}".format(message.chat.id) cursor.execute(sql) data = cursor.fetchone() # or use fetchone() except Exception: data = await get_data() cursor.execute("CREATE TABLE users (chatid INTEGER , name TEXT, click INTEGER, state INTEGER)") cursor.executemany("INSERT INTO users VALUES (?,?,?,?)", data) conn.commit() sql = "SELECT * FROM users where chatid={}".format(message.chat.id) cursor.execute(sql) data = cursor.fetchone() # or use fetchone() 

यदि हमें डेटाबेस में उपयोगकर्ता मिला है, तो हम बटन को संसाधित करते हैं:

  • "क्लिक" पर क्लिक करके हम इस उपयोगकर्ता के लिए क्लिक की संख्या को अपडेट करते हैं
  • जब आप "रेटिंग" पर क्लिक करते हैं तो हम उन पंद्रह लोगों की सूची प्रदर्शित करते हैं जिनके पास सबसे अधिक क्लिक होते हैं।

यदि आपको उपयोगकर्ता नहीं मिला, तो उसे एक त्रुटि लिखें।

  #      click     if data is not None: if message.text == '': sql = "UPDATE users SET click = {} WHERE chatid = {}".format(data[2]+1,message.chat.id) cursor.execute(sql) conn.commit() await bot.send_message(message.chat.id, ': {} '.format(data[2]+1)) #        10 if message.text == '': sql = "SELECT * FROM users ORDER BY click DESC LIMIT 15" cursor.execute(sql) newlist = cursor.fetchall() # or use fetchone() sql_count = "SELECT COUNT(chatid) FROM users" cursor.execute(sql_count) count=cursor.fetchone() rating=': {}\n'.format(count[0]) i=1 for user in newlist: rating=rating+str(i)+': '+user[1]+' - '+str(user[2])+'\n' i+=1 await bot.send_message(message.chat.id, rating) else: await bot.send_message(message.chat.id, '  ') 

उपयोगकर्ता पंजीकरण के लिए तर्क लिखें


हम डेटाबेस में उपयोगकर्ता को खोजने की कोशिश कर रहे हैं, अगर वह वहां नहीं है, तो तालिका में एक नई पंक्ति जोड़ें और बैकअप बनाएं।

यदि हम कोई त्रुटि पकड़ते हैं, तो हम अंतिम बैकअप को लोड करते हैं, तालिका को भरते हैं और पंजीकरण के प्रयास को दोहराते हैं।

 sql_select = "SELECT * FROM users where chatid={}".format(message.chat.id) sql_insert = "INSERT INTO users VALUES ({}, '{}', {},{})".format(message.chat.id,message.chat.first_name, 0, 0) try: cursor.execute(sql_select) data = cursor.fetchone() if data is None: cursor.execute(sql_insert) conn.commit() await save_data() except Exception: data = await get_data() cursor.execute("CREATE TABLE users (chatid INTEGER , name TEXT, click INTEGER, state INTEGER)") cursor.executemany("INSERT INTO users VALUES (?,?,?,?)", data) conn.commit() cursor.execute(sql_select) data = cursor.fetchone() if data is None: cursor.execute(sql_insert) conn.commit() await save_data() #   button = KeyboardButton('') button2 = KeyboardButton('') #  kb = ReplyKeyboardMarkup(resize_keyboard=True).add(button).add(button2) #     await bot.send_message(message.chat.id,' {}'.format(message.chat.first_name),reply_markup=kb) 

तो, अच्छी तरह से, और सबसे दिलचस्प।

Telergam सर्वर से डेटा को सहेजना और पुनः प्राप्त करना


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

  #-------------------- ------------------------- async def save_data(): sql = "SELECT * FROM users " cursor.execute(sql) data = cursor.fetchall() # or use fetchone() try: #     str_data=json.dumps(data) #      await bot.edit_message_media(InputMediaDocument(io.StringIO(str_data)), admin_id, config_id) except Exception as ex: print(ex) 

बैकअप पाने के लिए, हमें फ़ाइल से फ़ाइल को व्यवस्थापक से व्यवस्थापक को अग्रेषित करना होगा। फिर फ़ाइल के लिए पथ प्राप्त करें, url द्वारा डेटा पढ़ें और संपूर्ण बैकअप लौटाएं।

 # #-------------------- ------------------------- async def get_data(): #         forward_data = await bot.forward_message(admin_id, admin_id, config_id) #    ,   file_data = await bot.get_file(forward_data.document.file_id) #    url file_url_data = bot.get_file_url(file_data.file_path) #     json_file= urlopen(file_url_data).read() #    json     return json.loads(json_file) 

खैर, यह लगभग सभी है, यह केवल बैकअप बनाने और बॉट का परीक्षण करने के लिए एक टाइमर लिखने के लिए रहता है।
प्रत्येक 30 सेकंड में हमारे save_data () पद्धति को निष्पादित करने वाला एक धागा बनाएँ।

 def timer_start(): threading.Timer(30.0, timer_start).start() try: asyncio.run_coroutine_threadsafe(save_data(),bot.loop) except Exception as exc: pass 

खैर, मुख्य कार्यक्रम में, हम टाइमर और बॉट को ही शुरू करते हैं।

 #-------------------- ------------------------- if __name__ == '__main__': timer_start() executor.start_polling(dp, skip_updates=True) 

तो कोड को हल किया जा रहा है, यहाँ काम करने के मसौदे की कड़ी है

कैसे चलाना है?


  1. गिटहब से प्रोजेक्ट डाउनलोड करें। हम अजगर के लिए किसी भी विकास के माहौल में परियोजना शुरू करते हैं (उदाहरण के लिए: PyCharm)।
  2. विकास का वातावरण आवश्यक फ़ाइल से स्वचालित रूप से पुस्तकालयों को लोड करेगा।
  3. मेनफ्रेम में बोटफ़ादर से टोकन बदलें

  4. हम प्रोजेक्ट शुरू करते हैं
  5. दूसरे खाते से, "व्यवस्थापक" शब्द पर क्लिक करें / शुरू करें और लिखें

  6. प्रोजेक्ट को बंद करें और main.py फ़ाइल में admin_id और config_id भरें
  7. हम परियोजना शुरू करते हैं और उपयोगकर्ता खाते से हम शुरू दबाते हैं

  8. लाभ

परीक्षण और रेखांकन


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

ग्राफ ~ 100 अनुरोध-उत्तर के नमूनों से बने हैं। और नमूने का औसत प्रस्तुत किया गया है।

न्यूनतम विशेषताओं के साथ अमेज़ॅन आरडीएस पर पोस्टग्रेसीक्यूएल को तीसरे पक्ष के सर्वर पर डेटाबेस के रूप में उपयोग किया गया था।



एक मिलियन उपयोगकर्ताओं के साथ, बैकअप समय एक समस्या बन जाता है।



बैकअप का आकार पूरी तरह से आपके डेटा मॉडल पर निर्भर करता है, मेरे मामले में, एक मिलियन उपयोगकर्ताओं के साथ, 21 मेगाबाइट के साथ एक डेटा फ़ाइल प्राप्त की गई थी।



निष्कर्ष


डेटा संग्रहण की यह विधि एक मिलियन उपयोगकर्ताओं तक की परियोजनाओं के लिए समझ में आती है। यही है, एक प्रोटोटाइप या एक व्यक्तिगत स्टार्टअप के लिए, इस पद्धति को जीवन का अधिकार है।

नतीजतन, हमें एक पूर्ण स्टैंडअलोन क्लिकर मिला, जो दूरस्थ डेटाबेस से स्वतंत्र है।

यहाँ प्रोजेक्ट वर्णित है जो ऊपर उल्लिखित हैोकू: @Clicker_fast_bot

मैंने इस विचारधारा के साथ एक अधिक जटिल परियोजना भी लागू की: @Random_friend_bot

दो-व्यक्ति चैटरूम और चैट चैट की समानता, लेकिन केवल एक तार में।

वह संचार के लिए विपरीत लिंग के व्यक्ति के 100 किमी के दायरे में देख रहा है और एक नए वार्ताकार के साथ एक बंद चैट का एहसास करता है।

यदि यह दिलचस्प है, तो मैं परियोजना के स्रोत कोड को फेंक सकता हूं। इसके अलावा, अगर यह विषय प्रासंगिक है, तो अगले लेख में मैं बाहरी डेटाबेस के बिना रेस्ट एपी के निर्माण का वर्णन कर सकता हूं। यह एक ऐसा डेजैंगो-साइक्लाइट-टेलीग्राम स्टैक है।

मुझे किसी भी आलोचना में खुशी होगी, आपके ध्यान के लिए धन्यवाद!

Source: https://habr.com/ru/post/hi464865/


All Articles