7.1 ఇది ఎందుకు అవసరం

మేము ACID యొక్క అన్ని లక్షణాలు, వాటి ప్రయోజనం మరియు వినియోగ సందర్భాలను కొంత వివరంగా చర్చించాము. మీరు చూడగలిగినట్లుగా, అన్ని డేటాబేస్‌లు ACID హామీలను అందించవు, మెరుగైన పనితీరు కోసం వాటిని త్యాగం చేస్తాయి. అందువల్ల, మీ ప్రాజెక్ట్‌లో ACIDని అందించని డేటాబేస్ ఎంచుకోబడి ఉండవచ్చు మరియు మీరు అప్లికేషన్ వైపు అవసరమైన కొన్ని ACID కార్యాచరణను అమలు చేయాల్సి రావచ్చు. మరియు మీ సిస్టమ్ మైక్రోసర్వీస్‌గా లేదా ఇతర రకాల పంపిణీ చేయబడిన అప్లికేషన్‌గా రూపొందించబడి ఉంటే, ఒక సేవలో సాధారణ స్థానిక లావాదేవీ ఇప్పుడు పంపిణీ చేయబడిన లావాదేవీగా మారుతుంది - మరియు, వాస్తవానికి, దాని ACID స్వభావాన్ని కోల్పోతుంది, దీని డేటాబేస్ ప్రతి వ్యక్తిగత మైక్రోసర్వీస్ ACID అవుతుంది.

ట్రాన్సాక్షన్ మేనేజర్‌ని ఎలా క్రియేట్ చేయాలనే దానిపై నేను మీకు సమగ్రమైన గైడ్‌ను అందించదలచుకోలేదు, ఎందుకంటే ఇది చాలా పెద్దది మరియు సంక్లిష్టమైనది మరియు నేను కొన్ని ప్రాథమిక పద్ధతులను మాత్రమే కవర్ చేయాలనుకుంటున్నాను. మేము పంపిణీ చేయబడిన అప్లికేషన్‌ల గురించి మాట్లాడకపోతే, మీకు ACID హామీలు అవసరమైతే, అప్లికేషన్ వైపు ACIDని పూర్తిగా అమలు చేయడానికి ప్రయత్నించడానికి నాకు ఎటువంటి కారణం కనిపించదు - అన్నింటికంటే, రెడీమేడ్ సొల్యూషన్ తీసుకోవడం ప్రతి కోణంలో సులభం మరియు చౌకగా ఉంటుంది ( అంటే, ACIDతో కూడిన డేటాబేస్).

అయితే అప్లికేషన్ వైపు లావాదేవీలు చేయడంలో మీకు సహాయపడే కొన్ని టెక్నిక్‌లను నేను మీకు చూపించాలనుకుంటున్నాను. అన్నింటికంటే, ఈ టెక్నిక్‌లను తెలుసుకోవడం వలన వివిధ సందర్భాల్లో మీకు సహాయం చేయవచ్చు, లావాదేవీలు తప్పనిసరిగా చేయనివి కూడా మరియు మిమ్మల్ని మెరుగైన డెవలపర్‌గా మార్చగలవు (నేను ఆశిస్తున్నాను).

7.2 లావాదేవీ ప్రేమికులకు ప్రాథమిక సాధనాలు

ఆశావాద మరియు నిరాశావాద నిరోధం. ఇవి ఒకే సమయంలో యాక్సెస్ చేయగల కొన్ని డేటాపై రెండు రకాల లాక్‌లు.

ఆశావాదిఏకకాల ప్రాప్యత సంభావ్యత అంత గొప్పది కాదని ఊహిస్తుంది మరియు అందువల్ల ఇది క్రింది విధంగా చేస్తుంది: కావలసిన పంక్తిని చదువుతుంది, దాని సంస్కరణ సంఖ్యను గుర్తుంచుకుంటుంది (లేదా టైమ్‌స్టాంప్, లేదా చెక్‌సమ్ / హాష్ - మీరు డేటా స్కీమాను మార్చలేకపోతే మరియు సంస్కరణ కోసం నిలువు వరుసను జోడించవచ్చు లేదా టైమ్‌స్టాంప్), మరియు ఈ డేటా కోసం డేటాబేస్‌లో మార్పులను వ్రాయడానికి ముందు, ఈ డేటా యొక్క సంస్కరణ మారితే అది తనిఖీ చేస్తుంది. సంస్కరణ మారినట్లయితే, మీరు సృష్టించిన వైరుధ్యాన్ని ఎలాగైనా పరిష్కరించాలి మరియు డేటాను నవీకరించాలి (“కమిట్”), లేదా లావాదేవీని వెనక్కి తీసుకోవాలి (“రోల్‌బ్యాక్”). ఈ పద్ధతి యొక్క ప్రతికూలత ఏమిటంటే, ఇది TOCTOU అని సంక్షిప్తీకరించబడిన “టైమ్-ఆఫ్-చెక్ టు టైమ్-యూజ్” అనే దీర్ఘ పేరుతో బగ్‌కు అనుకూలమైన పరిస్థితులను సృష్టిస్తుంది: చెక్ మరియు రైట్ మధ్య వ్యవధిలో స్థితి మారవచ్చు. ఆశావాద లాకింగ్‌తో నాకు అనుభవం లేదు,

ఉదాహరణగా, నేను డెవలపర్ యొక్క రోజువారీ జీవితంలో ఒక సాంకేతికతను కనుగొన్నాను, అది ఆశావాద లాకింగ్ వంటిది - ఇది HTTP ప్రోటోకాల్. ప్రారంభ HTTP GET అభ్యర్థనకు ప్రతిస్పందన క్లయింట్ నుండి తదుపరి PUT అభ్యర్థనల కోసం ETag హెడర్‌ను కలిగి ఉంటుంది, దీనిని క్లయింట్ If-Match హెడర్‌లో ఉపయోగించవచ్చు. GET మరియు HEAD పద్ధతుల కోసం, సర్వర్ తనకు తెలిసిన ETtagలలో ఒకదానితో సరిపోలితే మాత్రమే అభ్యర్థించిన వనరును తిరిగి పంపుతుంది. PUT మరియు ఇతర అసురక్షిత పద్ధతుల కోసం, ఇది ఈ సందర్భంలో కూడా వనరును మాత్రమే లోడ్ చేస్తుంది. ETag ఎలా పని చేస్తుందో మీకు తెలియకుంటే, "ఫీడ్‌పార్సర్" లైబ్రరీని (ఇది RSS మరియు ఇతర ఫీడ్‌లను అన్వయించడంలో సహాయపడుతుంది) ఉపయోగించి ఇక్కడ ఒక మంచి ఉదాహరణ ఉంది.


>>> import feedparser 
>>> d = feedparser.parse('http://feedparser.org/docs/examples/atom10.xml') 
>>> d.etag 
'"6c132-941-ad7e3080"' 
>>> d2 = feedparser.parse('http://feedparser.org/docs/examples/atom10.xml', etag=d.etag) 
>>> d2.feed 
{} 
>>> d2.debug_message 
'The feed has not changed since you last checked, so the server sent no data.  This is a feature, not a bug!' 

నిరాశావాది, మరోవైపు, అదే డేటాపై లావాదేవీలు తరచుగా "కలుస్తాయి" అనే వాస్తవం నుండి ముందుకు సాగుతుంది మరియు అతని జీవితాన్ని సులభతరం చేయడానికి మరియు అనవసరమైన జాతి పరిస్థితులను నివారించడానికి, అతను తనకు అవసరమైన డేటాను బ్లాక్ చేస్తాడు. లాకింగ్ మెకానిజమ్‌ని అమలు చేయడానికి, మీరు మీ సెషన్ కోసం డేటాబేస్ కనెక్షన్‌ని నిర్వహించాలి (పూల్ నుండి కనెక్షన్‌లను లాగడం కంటే - ఈ సందర్భంలో మీరు ఆశావాద లాకింగ్‌తో పని చేయాల్సి ఉంటుంది) లేదా లావాదేవీ కోసం IDని ఉపయోగించండి , ఇది కనెక్షన్‌తో సంబంధం లేకుండా ఉపయోగించవచ్చు. నిరాశావాద లాకింగ్ యొక్క ప్రతికూలత ఏమిటంటే, దాని ఉపయోగం సాధారణంగా లావాదేవీల ప్రాసెసింగ్‌ను నెమ్మదిస్తుంది, కానీ మీరు డేటా గురించి ప్రశాంతంగా మరియు నిజమైన ఒంటరిగా పొందవచ్చు.

అదనపు ప్రమాదం, అయితే, సాధ్యమయ్యే ప్రతిష్టంభనలో దాగి ఉంది, దీనిలో అనేక ప్రక్రియలు ఒకదానికొకటి లాక్ చేయబడిన వనరుల కోసం వేచి ఉంటాయి. ఉదాహరణకు, ఒక లావాదేవీకి A మరియు B వనరులు అవసరం. ప్రాసెస్ 1 వనరు Aని ఆక్రమించింది మరియు ప్రాసెస్ 2 వనరు Bని ఆక్రమించింది. రెండు ప్రక్రియలలో ఏదీ అమలును కొనసాగించదు. ఈ సమస్యను పరిష్కరించడానికి వివిధ మార్గాలు ఉన్నాయి - నేను ఇప్పుడు వివరాల్లోకి వెళ్లకూడదనుకుంటున్నాను, కాబట్టి ముందుగా వికీపీడియాను చదవండి, కానీ సంక్షిప్తంగా, లాక్ సోపానక్రమాన్ని సృష్టించే అవకాశం ఉంది. మీరు ఈ కాన్సెప్ట్‌ను మరింత వివరంగా తెలుసుకోవాలనుకుంటే, “డినింగ్ ఫిలాసఫర్స్ ప్రాబ్లమ్” (“డైనింగ్ ఫిలాసఫర్స్ ప్రాబ్లమ్”) గురించి మీ మెదడును ర్యాక్ చేయడానికి మిమ్మల్ని ఆహ్వానిస్తారు.

రెండు తాళాలు ఒకే దృష్టాంతంలో ఎలా ప్రవర్తిస్తాయో ఇక్కడ ఒక మంచి ఉదాహరణ ఉంది.

తాళాల అమలుకు సంబంధించి. నేను వివరాల్లోకి వెళ్లాలనుకోవడం లేదు, కానీ పంపిణీ చేయబడిన సిస్టమ్‌ల కోసం లాక్ మేనేజర్‌లు ఉన్నారు, ఉదాహరణకు: ZooKeeper, Redis, etcd, Consul.

7.3 ఆపరేషన్ల ఐడెంపోటెన్సీ

ఐడెంపోటెంట్ కోడ్ సాధారణంగా ఒక మంచి అభ్యాసం, మరియు డెవలపర్ లావాదేవీలను ఉపయోగించాలా వద్దా అనే దానితో సంబంధం లేకుండా దీన్ని చేయగలగడం అతనికి చాలా మంచిది. ఐడెంపోటెన్సీ అనేది ఒక ఆపరేషన్ యొక్క లక్షణం, ఆ ఆపరేషన్ ఒక వస్తువుకు మళ్లీ వర్తించినప్పుడు అదే ఫలితాన్ని ఉత్పత్తి చేస్తుంది. ఫంక్షన్ అని పిలుస్తారు - ఫలితాన్ని ఇచ్చింది. ఒక సెకను లేదా ఐదు తర్వాత మళ్లీ కాల్ చేస్తే - అదే ఫలితాన్ని ఇచ్చింది. వాస్తవానికి, డేటాబేస్లోని డేటా మారినట్లయితే, ఫలితం భిన్నంగా ఉంటుంది. మూడవ సిస్టమ్‌లోని డేటా ఒక ఫంక్షన్‌పై ఆధారపడి ఉండకపోవచ్చు, కానీ ఏదైనా చేసేది తప్పనిసరిగా ఊహించదగినదిగా ఉండాలి.

అసమర్థత యొక్క అనేక వ్యక్తీకరణలు ఉండవచ్చు. వాటిలో ఒకటి మీ కోడ్‌ను ఎలా వ్రాయాలనే దానిపై సిఫార్సు మాత్రమే. ఒక పని చేయడమే ఉత్తమమైన పని అని మీకు గుర్తుందా? మరియు ఈ ఫంక్షన్ కోసం యూనిట్ పరీక్షలు రాయడం మంచి విషయం ఏమిటి? మీరు ఈ రెండు నియమాలకు కట్టుబడి ఉంటే, మీరు ఇప్పటికే మీ విధులు బలహీనంగా ఉండే అవకాశాన్ని పెంచుతారు. గందరగోళాన్ని నివారించడానికి, ఐడెంపోటెంట్ ఫంక్షన్‌లు తప్పనిసరిగా “స్వచ్ఛమైనవి” (“ఫంక్షన్ స్వచ్ఛత” అనే అర్థంలో) ఉండవని నేను స్పష్టం చేస్తాను. ప్యూర్ ఫంక్షన్‌లు అంటే ఇన్‌పుట్‌లో స్వీకరించిన డేటాను ఏ విధంగానూ మార్చకుండా మరియు ప్రాసెస్ చేసిన ఫలితాన్ని అందించకుండా వాటిపై మాత్రమే పనిచేసే విధులు. ఫంక్షనల్ ప్రోగ్రామింగ్ టెక్నిక్‌లను ఉపయోగించి మీ అప్లికేషన్‌ను స్కేల్ చేయడానికి మిమ్మల్ని అనుమతించే ఫంక్షన్‌లు ఇవి. మేము కొన్ని సాధారణ డేటా మరియు డేటాబేస్ గురించి మాట్లాడుతున్నాము కాబట్టి, మా విధులు స్వచ్ఛంగా ఉండే అవకాశం లేదు,

ఇది స్వచ్ఛమైన ఫంక్షన్:


def square(num: int) -> int: 
	return num * num 

కానీ ఈ ఫంక్షన్ స్వచ్ఛమైనది కాదు, కానీ ఐడెంపోటెంట్ (దయచేసి నేను ఈ ముక్కల నుండి కోడ్‌ను ఎలా వ్రాస్తాను అనే దాని గురించి తీర్మానాలు చేయవద్దు):


def insert_data(insert_query: str, db_connection: DbConnectionType) -> int: 
  db_connection.execute(insert_query) 
  return True 

చాలా పదాలకు బదులుగా, నేను ఐడెంపోటెంట్ ప్రోగ్రామ్‌లను ఎలా వ్రాయాలో నేర్చుకోవలసి వచ్చింది అనే దాని గురించి నేను మాట్లాడగలను. నేను AWSతో చాలా పని చేస్తాను, మీరు ఇప్పుడు చూడగలరు మరియు AWS లాంబ్డా అనే సేవ ఉంది. లాంబ్డా సర్వర్‌లను జాగ్రత్తగా చూసుకోకుండా మిమ్మల్ని అనుమతిస్తుంది, కానీ కొన్ని ఈవెంట్‌లకు ప్రతిస్పందనగా లేదా షెడ్యూల్ ప్రకారం అమలు చేసే కోడ్‌ను లోడ్ చేస్తుంది. ఈవెంట్ అనేది మెసేజ్ బ్రోకర్ ద్వారా బట్వాడా చేయబడిన సందేశాలు కావచ్చు. AWSలో, ఈ బ్రోకర్ AWS SNS. AWSతో పని చేయని వారికి కూడా ఇది స్పష్టంగా ఉండాలని నేను భావిస్తున్నాను: ఛానెల్‌ల (“టాపిక్‌లు”) ద్వారా సందేశాలను పంపే బ్రోకర్ మా వద్ద ఉన్నారు మరియు ఈ ఛానెల్‌లకు సభ్యత్వం పొందిన మైక్రోసర్వీస్‌లు సందేశాలను స్వీకరిస్తాయి మరియు వాటిపై ఏదో ఒకవిధంగా ప్రతిస్పందిస్తాయి.

సమస్య ఏమిటంటే SNS సందేశాలను "కనీసం ఒక్కసారైనా" ("కనీసం-ఒకసారి డెలివరీ") అందిస్తుంది. దాని అర్థం ఏమిటి? ఆ వెంటనే లేదా తరువాత మీ లాంబ్డా కోడ్ రెండుసార్లు కాల్ చేయబడుతుంది. మరియు ఇది నిజంగా జరుగుతుంది. మీ ఫంక్షన్‌కు ధీమాగా ఉండాల్సిన అనేక దృశ్యాలు ఉన్నాయి: ఉదాహరణకు, ఒక ఖాతా నుండి డబ్బును ఉపసంహరించుకున్నప్పుడు, ఎవరైనా అదే మొత్తాన్ని రెండుసార్లు విత్‌డ్రా చేయాలని మేము ఆశించవచ్చు, అయితే ఇవి నిజంగా 2 స్వతంత్ర సమయాలు అని మేము నిర్ధారించుకోవాలి - మరో మాటలో చెప్పాలంటే, ఇవి 2 వేర్వేరు లావాదేవీలు మరియు ఒకటి పునరావృతం కాదు.

మార్పు కోసం, నేను మరొక ఉదాహరణ ఇస్తాను - అభ్యర్థనల ఫ్రీక్వెన్సీని APIకి పరిమితం చేయడం ("రేటు పరిమితి"). మా లాంబ్డా ఒక నిర్దిష్ట user_idతో ఈవెంట్‌ను అందుకుంటుంది, దాని కోసం ఆ IDని కలిగి ఉన్న వినియోగదారు మా APIలలో కొన్నింటికి అతని సాధ్యమయ్యే అభ్యర్థనల సంఖ్యను పూర్తి చేశారో లేదో తనిఖీ చేయాలి. మేము AWS నుండి DynamoDBలో చేసిన కాల్‌ల విలువను నిల్వ చేయవచ్చు మరియు మా ఫంక్షన్‌కు ప్రతి కాల్‌తో దాన్ని 1 పెంచవచ్చు.

అయితే ఈ లాంబ్డా ఫంక్షన్‌ని ఒకే ఈవెంట్‌కి రెండుసార్లు పిలిస్తే? మార్గం ద్వారా, మీరు lambda_handler() ఫంక్షన్ యొక్క వాదనలకు శ్రద్ధ చూపారా. రెండవ ఆర్గ్యుమెంట్, AWS లాంబ్డాలోని సందర్భం డిఫాల్ట్‌గా ఇవ్వబడింది మరియు ప్రతి ప్రత్యేక కాల్ కోసం రూపొందించబడే request_idతో సహా వివిధ మెటాడేటాను కలిగి ఉంటుంది. దీని అర్థం ఇప్పుడు, టేబుల్‌లో చేసిన కాల్‌ల సంఖ్యను నిల్వ చేయడానికి బదులుగా, మేము request_id జాబితాను నిల్వ చేయవచ్చు మరియు ప్రతి కాల్‌లో మా లాంబ్డా ఇచ్చిన అభ్యర్థన ఇప్పటికే ప్రాసెస్ చేయబడిందో లేదో తనిఖీ చేస్తుంది:

import json
import os
from typing import Any, Dict

from aws_lambda_powertools.utilities.typing import LambdaContext  # needed only for argument type annotation
import boto3

limit = os.getenv('LIMIT')

def handler_name(event: Dict[str: Any], context: LambdaContext):

	request_id = context.aws_request_id

	# We find user_id in incoming event
	user_id = event["user_id"]

	# Our table for DynamoDB
	table = boto3.resource('dynamodb').Table('my_table')

	# Doing update
	table.update_item(
    	Key={'pkey': user_id},
    	UpdateExpression='ADD requests :request_id',
    	ConditionExpression='attribute_not_exists (requests) OR (size(requests) < :limit AND NOT contains(requests, :request_id))',
    	ExpressionAttributeValues={
        	':request_id': {'S': request_id},
        	':requests': {'SS': [request_id]},
        	':limit': {'N': limit}
    	}
	)

	# TODO: write further logic

	return {
    	"statusCode": 200,
    	"headers": {
        	"Content-Type": "application/json"
    	},
    	"body": json.dumps({
        	"status ": "success"
    	})
	}

నా ఉదాహరణ నిజానికి ఇంటర్నెట్ నుండి తీసుకోబడినందున, నేను అసలు మూలానికి లింక్‌ను వదిలివేస్తాను, ప్రత్యేకించి ఇది కొంచెం ఎక్కువ సమాచారాన్ని ఇస్తుంది.

భాగస్వామ్య డేటాను లాక్ చేయడానికి ప్రత్యేకమైన లావాదేవీ ID వంటిది ఉపయోగించవచ్చని నేను ఇంతకు ముందు ఎలా పేర్కొన్నానో గుర్తుందా? ఇది ఆపరేషన్‌లను బలహీనంగా చేయడానికి కూడా ఉపయోగించవచ్చని మేము ఇప్పుడు తెలుసుకున్నాము. అలాంటి IDలను మీరే ఏయే మార్గాల్లో రూపొందించుకోవచ్చో తెలుసుకుందాం.