<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Rahul Jindal</title>
    <description>The latest articles on Forem by Rahul Jindal (@rahul_jindal).</description>
    <link>https://forem.com/rahul_jindal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F939248%2F3d2525d4-9ba3-4bc1-9d31-d9108e734a6d.jpg</url>
      <title>Forem: Rahul Jindal</title>
      <link>https://forem.com/rahul_jindal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rahul_jindal"/>
    <language>en</language>
    <item>
      <title>Currying in JavaScript</title>
      <dc:creator>Rahul Jindal</dc:creator>
      <pubDate>Mon, 30 Jan 2023 03:18:35 +0000</pubDate>
      <link>https://forem.com/rahul_jindal/currying-in-javascript-49be</link>
      <guid>https://forem.com/rahul_jindal/currying-in-javascript-49be</guid>
      <description>&lt;p&gt;&lt;strong&gt;Currying&lt;/strong&gt; is a functional programming technique that involves transforming a function with multiple arguments into a series of functions that each take a single argument.&lt;/p&gt;

&lt;p&gt;In JavaScript, currying involves breaking down a function that takes multiple arguments into a series of functions, each of which takes a single argument. The first function returns another function that takes the next argument, and so on, until all arguments have been passed to the function. The final function then returns the result.&lt;/p&gt;

&lt;p&gt;Here is an example of normal function in JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function add(a, b) {
  return a + b;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is an example of a curried function in JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function add(a) {
  return function(b) {
    return a + b;
  };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;p&gt;Understanding &lt;strong&gt;closures&lt;/strong&gt; is a pre-requisite to understanding currying in JavaScript. Currying leverages the closure property of functions in JavaScript to capture arguments and build up a complete set of arguments over time. By using closures, currying allows you to partially apply arguments to a function, and create new functions with a fixed set of arguments that can be called later with the remaining arguments. Without a solid understanding of closures, it can be difficult to understand how currying works and why it is useful.&lt;/p&gt;




&lt;h2&gt;
  
  
  Benefits of Currying
&lt;/h2&gt;

&lt;p&gt;1 &lt;strong&gt;Reusable functions:&lt;/strong&gt; Currying allows you to create reusable functions that can be partially applied with some arguments and then used multiple times with different arguments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const add = (a) =&amp;gt; (b) =&amp;gt; a + b;

const add5 = add(5);
const add10 = add(10);

console.log(add5(3)); // 8
console.log(add10(3)); // 13
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 &lt;strong&gt;Readability:&lt;/strong&gt; Currying can make code easier to read and understand by breaking down complex functions into smaller, more manageable functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const add = (a) =&amp;gt; (b) =&amp;gt; (c) =&amp;gt; a + b + c;

const add5 = add(5);
const add5And10 = add5(10);

console.log(add5And10(3)); // 18
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3 &lt;strong&gt;Composition:&lt;/strong&gt; Currying allows you to compose functions together to create new functions, making it easier to write and manage code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const add = (a) =&amp;gt; (b) =&amp;gt; a + b;
const multiply = (a) =&amp;gt; (b) =&amp;gt; a * b;

const add5 = add(5);
const double = multiply(2);

const doubleAndAdd5 = (x) =&amp;gt; add5(double(x));

console.log(doubleAndAdd5(3)); // 11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The use of currying in this example makes the code more composable and maintainable by breaking down complex functions into smaller, simpler functions that can be composed together to create the final result.&lt;/p&gt;

&lt;p&gt;4 &lt;strong&gt;Easier testing:&lt;/strong&gt; Functions that are curried are easier to test, as you can test each individual function in isolation.&lt;/p&gt;

&lt;p&gt;5 &lt;strong&gt;Better code organization:&lt;/strong&gt; By breaking down functions into smaller, more manageable functions, currying can help to improve the organization of your code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const add = (a) =&amp;gt; (b) =&amp;gt; a + b;
const multiply = (a) =&amp;gt; (b) =&amp;gt; a * b;

const add10 = add(10);
const multiplyBy5 = multiply(5);

const add10AndMultiplyBy5 = (n) =&amp;gt; add10(multiplyBy5(n));

console.log(add10AndMultiplyBy5(2)); // 20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The use of currying in this example improves code organization by breaking down the simple &lt;code&gt;add&lt;/code&gt; and &lt;code&gt;multiply&lt;/code&gt; functions into smaller, more manageable functions that can be composed together in a single expression to achieve the desired result. This can help to make the code more readable, maintainable, and reusable.&lt;/p&gt;

&lt;p&gt;6 &lt;strong&gt;Improved performance:&lt;/strong&gt; Currying can lead to improved performance, as partially applied functions can be optimized and cached, reducing the number of function calls and improving performance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const memoizedFetch = (() =&amp;gt; {
  const cache = {};
  return (url) =&amp;gt; {
    if (cache[url]) return Promise.resolve(cache[url]);
    return fetch(url)
      .then((response) =&amp;gt; response.json())
      .then((data) =&amp;gt; {
        cache[url] = data;
        return data;
      });
  };
})();

const fetchUsers = memoizedFetch("https://jsonplaceholder.typicode.com/users");
const fetchPosts = memoizedFetch("https://jsonplaceholder.typicode.com/posts");
const fetchTodos = memoizedFetch("https://jsonplaceholder.typicode.com/todos");

fetchUsers.then(console.log); // [{...}, {...}, ...]
fetchPosts.then(console.log); // [{...}, {...}, ...]
fetchTodos.then(console.log); // [{...}, {...}, ...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The use of currying in this example improves performance by allowing us to cache the results of previous requests and avoid making the same request multiple times. This can be particularly useful when the request is time-consuming or has a high latency, as it allows us to cache the result and reuse it whenever possible.&lt;/p&gt;

&lt;p&gt;7 &lt;strong&gt;Better function composition:&lt;/strong&gt; When functions are curried, they can be composed in a more flexible way, making it easier to write complex functions and making the code more maintainable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const multiply = (a) =&amp;gt; (b) =&amp;gt; a * b;
const add = (a) =&amp;gt; (b) =&amp;gt; a + b;
const modulo = (a) =&amp;gt; (b) =&amp;gt; b % a;

const isOdd = modulo(2);
const double = multiply(2);
const increment = add(1);

const processNumber = (num) =&amp;gt;
  double(increment(isOdd(num) ? num : increment(num)));

console.log(processNumber(2)); // 6
console.log(processNumber(3)); // 8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Applications of Currying
&lt;/h2&gt;

&lt;p&gt;1 &lt;strong&gt;Event handling:&lt;/strong&gt; Currying can be used to simplify event handling in a program by partially applying event handlers with specific arguments, making it easier to handle similar events in a generic way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const handleClick = (elementId) =&amp;gt; (event) =&amp;gt; {
  console.log(`Clicked on element with id: ${elementId}`);
};

const button1 = document.getElementById('button1');
button1.addEventListener('click', handleClick('button1'));

const button2 = document.getElementById('button2');
button2.addEventListener('click', handleClick('button2'));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 &lt;strong&gt;API calls:&lt;/strong&gt; Currying can be used to abstract API calls and make them more flexible and reusable by partially applying them with specific parameters, reducing the need to repeat the same code for similar API calls.&lt;/p&gt;

&lt;p&gt;3 &lt;strong&gt;Data processing:&lt;/strong&gt; Currying can be used to simplify data processing pipelines by partially applying functions with specific parameters, making it easier to process data in a modular and composable way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const curry = (fn) =&amp;gt; {
  return function curried(...args) {
    if (args.length &amp;gt;= fn.length) {
      return fn.apply(this, args);
    } else {
      return function(...args2) {
        return curried.apply(this, [...args, ...args2]);
      };
    }
  };
};

const filterData = curry((fn, data) =&amp;gt; data.filter(fn));
const filterNumbers = filterData((x) =&amp;gt; typeof x === "number");
const result = filterNumbers([1, "hello", 3, "world", 5]); 

console.log(result); // [1, 3, 5]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, currying is a concept from functional programming that involves transforming a function with multiple arguments into a sequence of functions, each taking a single argument. Currying can make it easier to reuse and compose functions, leading to more maintainable and readable code. While not directly useful in user interface development, it can be a helpful concept in functional programming that can lead to improved code quality. Whether or not to use currying in a project depends on the specific needs and constraints of that project, and its use should be evaluated based on the specific requirements.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>discuss</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Consistent Hashing</title>
      <dc:creator>Rahul Jindal</dc:creator>
      <pubDate>Wed, 18 Jan 2023 12:42:06 +0000</pubDate>
      <link>https://forem.com/rahul_jindal/consistent-hashing-4km3</link>
      <guid>https://forem.com/rahul_jindal/consistent-hashing-4km3</guid>
      <description>&lt;p&gt;Consistent hashing is a method of distributing requests among a dynamic set of servers which will allows for a more efficient use of resources and improved performance, as well as the ability to easily add or remove servers without disrupting the system. But, Before we discuss consistent hashing it is important to know what is hashing.&lt;/p&gt;

&lt;p&gt;Hashing is a technique of converting data into a fixed-size output called a hash or a digest. An example of hashing is to use modulo in a distributed caching system with 4 servers ( s0, s1, s2, s3 ). The hash function will use IP ( 192.168.1.100 ) of the incoming request as the key and divide it with the total number of servers( 4 ), then remainder will be the server to which request should be redirected to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hash(192.168.1.100) = (192.168.1.100 % 4) = 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, In the above example incoming request would be assigned to s0. Given below is an example how mapping to different servers will look like when multiple requests are being sent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsily1gkk42pwl2el92fi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsily1gkk42pwl2el92fi.png" alt="Data Distribution by Modulo operator as hash function" width="780" height="762"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Modulo Operator Limitations as Hash Function
&lt;/h2&gt;

&lt;p&gt;In practice, it is not recommended to use modulo operator as a simple hash function, as it can lead to poor distribution of keys and poor performance. Suppose In the above example, a server gets removed. Then keys distribution will be like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6y0961730hvm6vz88jh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6y0961730hvm6vz88jh.png" alt="Data Distribution after removing a server" width="756" height="722"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we need to remap all the request to the different servers which will lead the client to fetch data from the wrong servers and cause cache misses with uneven load distribution. Because of these issues consistent hashing came into play.&lt;/p&gt;




&lt;h2&gt;
  
  
  Consistent Hashing Working
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;A virtual circle, also known as a &lt;code&gt;hash ring&lt;/code&gt;, is created, where each server is assigned a unique position on the ring.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A hash function, such as SHA-1 or MD5, is used to map each server and each data item &lt;em&gt;( can be IP or any kind of data like key in key-value pair systems)&lt;/em&gt; to a unique position on the virtual circle. Hash function also defines the &lt;code&gt;hash space&lt;/code&gt; which refers to the range of values that the hash function can output. The hash space of SHA-1 is 2¹⁶⁰ which means there are 1.46 x 10⁴⁸ unique hash values that can be produced by the SHA-1 hash function.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu94cra2m7x1leejnpfqc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu94cra2m7x1leejnpfqc.png" alt="Server and Data Item Positioning on hash ring" width="800" height="669"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When a request for a data item is received, the hash function is used to determine the position of the data item on the ring.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The request is then directed to the server whose position on the ring is closest to the position of the data item by moving in clockwise direction.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm6ta73ryqjj5z39vuzxd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm6ta73ryqjj5z39vuzxd.png" alt="Data Item Mapping with nearby servers" width="800" height="619"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When a server is added or removed from the system, the positions of the other servers on the ring do not change, but the data items that were hashed to positions on the ring that are closest to the new or removed server, are re-hashed to the new closest server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This way, only a small subset of data items need to be re-hashed when a server is added or removed, minimizing the disruption to the system.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F85gefsdvotuaqjno071d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F85gefsdvotuaqjno071d.png" alt="Server Remapping on Adding new Server in Consistent Hashing" width="800" height="634"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3jwunpsp5uhyqcbw5is4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3jwunpsp5uhyqcbw5is4.png" alt="Server Remapping on Removing a Server in Consistent Hashing" width="800" height="596"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Hash Space and Hash Ring Limitations
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hash space limitations:&lt;/strong&gt; The size of the hash space, which is the range of values that the hash function can output, can be a limiting factor in consistent hashing. If the hash space is too small, it may not be able to accommodate all the servers or data items in the system, resulting in a high number of collisions. On the other hand, if the hash space is too large, it may not make efficient use of resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hash ring limitations:&lt;/strong&gt; The use of a hash ring can also have limitations. The number of positions on the hash ring is fixed, and if the number of servers or data items exceeds the number of positions, collisions will occur.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalability:&lt;/strong&gt; Consistent hashing can become less efficient as the number of servers or data items increases, as the number of remappings required can become large.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Load balancing:&lt;/strong&gt; Consistent hashing does not take into account the load on each server, so it may not distribute the load evenly among the servers.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl9078gthp7jnljvyr3cp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl9078gthp7jnljvyr3cp.png" alt="Uneven Data Distribution causing excess load on Server 2" width="800" height="647"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance:&lt;/strong&gt; Consistent hashing can have poor performance when the number of collisions increases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complexity:&lt;/strong&gt; Consistent hashing can be computationally expensive and time-consuming when a server is added or removed from the system, as it requires remapping of data items or requests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limited fault tolerance:&lt;/strong&gt; Consistent Hashing doesn't take into account the fault tolerance, if a node goes down it will lead to a redistribution of keys which can cause a temporary disruption in the system.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To overcome some of the limitations of hash ring and hash space limitation, virtual nodes are being introduced.&lt;/p&gt;




&lt;h2&gt;
  
  
  Virtual Nodes
&lt;/h2&gt;

&lt;p&gt;In consistent hashing, virtual nodes are used to improve the distribution of data or requests among the servers. Each physical server in the system is assigned multiple virtual nodes or "tokens" and these tokens are used to determine the positions on the hash ring. This allows for a more even distribution of data or requests among the servers and can improve the performance of the system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fipn86u7oct7wa8xjb5ma.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fipn86u7oct7wa8xjb5ma.png" alt="Distributions of Server 0 and Server 1 over multiple virtual nodes" width="800" height="626"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above diagram we can clearly see servers are distributed at different positions on the hash ring which provides more even data distribution and enhanced load balancing on each server. Each virtual node is being read as s0_0, s0_1, s0_2 where s0 is the server and 0,1,2 being the position of the virtual node on hash ring.&lt;/p&gt;




&lt;h2&gt;
  
  
  Benefits of Virtual Nodes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hash space limitations:&lt;/strong&gt; By using virtual nodes, the size of the hash space can be increased, reducing the number of collisions that occur. For example, if a physical server is assigned 4 virtual nodes ( s0_0, s0_1, s0_2, s0_3 ), it would have 4 times more positions on the hash ring keeping the hashed value constant than a physical server with 1 virtual node ( s0_0 ). This increases the number of possible positions on the hash ring, reducing the chance of collisions and improving the distribution of data or requests among the servers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Hash ring limitations:&lt;/strong&gt; The use of virtual nodes allows for a larger number of positions on the hash ring, increasing the number of servers or data items that can be accommodated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalability:&lt;/strong&gt; Virtual nodes can improve the scalability of consistent hashing, as it can accommodate a large number of servers or data items without a significant increase in the number of remappings required.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Load balancing:&lt;/strong&gt; Virtual nodes can improve load balancing by distributing the load more evenly among the servers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance:&lt;/strong&gt; Using virtual nodes can improve the performance of consistent hashing, as it reduces the number of collisions and remappings required.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complexity:&lt;/strong&gt; Using virtual nodes can reduce the computational complexity of consistent hashing, as it reduces the number of remappings required when a server is added or removed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fault tolerance:&lt;/strong&gt; Virtual nodes can increase the fault tolerance of the system, because if a node goes down, the load is distributed among the other virtual nodes and physical nodes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, consistent hashing is a method of distributing requests among a dynamic set of servers. It uses a hash function to map each server and data item to a unique position on a virtual circle, or "hash ring," and then uses the hash of the request to determine which server the request should be directed to. The key benefit of consistent hashing is that it allows for the addition or removal of servers with minimal remapping of requests to servers.&lt;/p&gt;

&lt;p&gt;Consistent hashing is used in several distributed systems, such as distributed caching, distributed storage, and distributed databases, to distribute the load of data and requests among the available servers. This allows for a more efficient use of resources and improved performance, as well as the ability to easily add or remove servers without disrupting the system.&lt;/p&gt;

&lt;p&gt;However, consistent hashing has some limitations, such as hash space limitations, hash ring limitations, scalability, load balancing, performance, and complexity. To overcome these limitations, virtual nodes, dynamic consistent hashing, rendezvous hashing, and Maglev hashing have been proposed as alternative methods.&lt;/p&gt;

&lt;p&gt;Overall, consistent hashing is a useful technique for distributing data or requests among servers or resources in a dynamic and efficient manner, but it is important to consider the trade-offs involved and to choose the best method for the specific use case.&lt;/p&gt;

</description>
      <category>discuss</category>
    </item>
    <item>
      <title>"this" keyword in JavaScript</title>
      <dc:creator>Rahul Jindal</dc:creator>
      <pubDate>Wed, 18 Jan 2023 04:45:20 +0000</pubDate>
      <link>https://forem.com/rahul_jindal/this-keyword-in-javascript-4a08</link>
      <guid>https://forem.com/rahul_jindal/this-keyword-in-javascript-4a08</guid>
      <description>&lt;p&gt;In JavaScript, &lt;code&gt;this&lt;/code&gt; keyword stores the reference of the object. Unlike in many other languages this is not bounded to a class in JavaScript, it's value is being evaluated during the run-time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;this keyword take the reference of the object who is calling the method.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const consumer = { description: "Consumes Something" }
const producer = { description: "Produces Something" }

function printDescription() {
   console.log( this.description );
}

// Same printDescription function is being used in both the Objects
consumer.printDescription = printDescription;
producer.printDescription = printDescription;

consumer.printDescription(); // Output:- "Consumes Something"
producer.printDescription(); // Output:- "Produces Something"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, when &lt;code&gt;consumer.printDescription()&lt;/code&gt; is called , &lt;code&gt;this&lt;/code&gt; will store the reference of the object who is calling the method, which is consumer in this case and it will give the description provided in the consumer object. Similarly when &lt;code&gt;producer.printDescription()&lt;/code&gt; is being called, &lt;code&gt;this&lt;/code&gt; will refer to the producer object and console "Produces Something".&lt;/p&gt;




&lt;h2&gt;
  
  
  Using "this" keyword in function
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;this&lt;/code&gt; keyword can even be used inside a function without using an object&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function printDescription() {
   console.log( this.description );
}

printDescription(); // Output:- undefined
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In non-strict mode, value of &lt;code&gt;this&lt;/code&gt; in such cases will be the global &lt;code&gt;window&lt;/code&gt; object and properties existing on the window object can be accessible via &lt;code&gt;this&lt;/code&gt; keyword.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;window.description = "Description added in window object"

function printDescription() {
   console.log( this.description );
}

printDescription(); // Output:- "Description added in window object"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While in strict mode, &lt;code&gt;this&lt;/code&gt; will be undefined and above example will give an error for trying to access description on undefined.&lt;/p&gt;




&lt;h2&gt;
  
  
  No "this" in Arrow function
&lt;/h2&gt;

&lt;p&gt;Arrow function do not have their own &lt;code&gt;this&lt;/code&gt;, If we &lt;code&gt;use&lt;/code&gt; this inside the arrow function, then it is taken from the outer function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const consumer = {
   description: "Consumes Something",
   printDescription: function () {
       const arrow = () =&amp;gt; { console.log(this.description) }
       arrow();
   }
}

consumer.printDescription(); // Output:- "Consumes Something"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, consumer calls the &lt;code&gt;printDescription&lt;/code&gt; method, because of which &lt;code&gt;this&lt;/code&gt; inside the &lt;code&gt;printDescription&lt;/code&gt; will have the reference of consumer object.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;printDescription&lt;/code&gt; method, when arrow function is being called, &lt;code&gt;this&lt;/code&gt; will be taken from the outer function which currently has the reference of "consumer" object and it will result in the description value stored inside consumer object.&lt;/p&gt;

&lt;p&gt;This special feature of arrow function helps in resolving the issue of losing reference of &lt;code&gt;this&lt;/code&gt; keyword in case of nested function calls.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const consumer = {
   description: "Consumes Something",
   printDescription: function () {
       function fn() { console.log(this.description) }
       fn();
   }
}

consumer.printDescription(); // Output:- undefined
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When printDescription is called, &lt;code&gt;this&lt;/code&gt; will have the reference of consumer object, because consumer is calling the &lt;code&gt;printDescription&lt;/code&gt; method, but inside the &lt;code&gt;fn&lt;/code&gt; function in &lt;code&gt;printDescription&lt;/code&gt; method, &lt;code&gt;this&lt;/code&gt; will have the reference of global window object because no other object is calling the &lt;code&gt;fn&lt;/code&gt; function which is similar to the case which we discussed above in &lt;strong&gt;Using "this" keyword in function&lt;/strong&gt; section.&lt;/p&gt;

&lt;p&gt;This will lead to losing the reference of consumer object in the nested function call, which can be resolved with the help of arrow function.&lt;/p&gt;




&lt;h2&gt;
  
  
  Alternative solution for losing "this" keyword in nested function calls
&lt;/h2&gt;

&lt;p&gt;There is an alternative solution to keep the reference of main object inside the nested calls without the use of arrow functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const consumer = {
   description: "Consumes Something",
   printDescription: function () {
       const that = this;
       function fn() { console.log(that.description) }
       fn();
   }
}

consumer.printDescription() // Output:- "Consumes Something"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can store the value of &lt;code&gt;this&lt;/code&gt; keyword in some variable and use that variable inside the nested function call in place of &lt;code&gt;this&lt;/code&gt; keyword.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>this</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
