[LintCode] Load Balancer

本文介绍了一种使用哈希表和数组结合的方式实现的负载均衡器,该方案支持服务器的快速添加与移除,并能随机选取集群中的服务器。通过将服务器ID映射到数组索引,实现了O(1)级别的添加、移除及随机选取操作。

Implement a load balancer for web servers. It provide the following functionality:

  1. Add a new server to the cluster => add(server_id).
  2. Remove a bad server from the cluster => remove(server_id).
  3. Pick a server in the cluster randomly with equal probability => pick().
Example

At beginning, the cluster is empty => {}.

add(1)
add(2)
add(3)
pick()
>> 1         // the return value is random, it can be either 1, 2, or 3.
pick()
>> 2
pick()
>> 1
pick()
>> 3
remove(1)
pick()
>> 2
pick()
>> 3
pick()
>> 3

Analysis
To implement add/remove server id in O(1), we can only use hash map. However, it is not easy to
implement pick randomly.

Using array will be easy to implement pick random method. But using array alone does not give us O(1) remove operation.
Instead, we get a O(n) remove.

The solution is to use both a hash map and an arraylist to get O(1) add/remove/pick operations. 

The arraylist stores all server ids and the hash map maps server id to its index in the arraylist. 

Add:  add a new server id to the end of the arraylist; add a new key value pair for this newly added server id in the hashmap.

Remove:  Get the arraylist index of the server to be removed from the hash map, then remove the key value pair.

      Swap the server id at the end of the arraylist with the server id that is to be removed.

      Update the arraylist index of the swapped server id in the hash map. 

      Remove the server index at the end of the arraylist.

Pick:  use rand to randomly pick a arraylist index.

 

The key points of the above solution are:

1. To achieve O(1) deletion in the arraylist,

swap the element that needs to be removed with the last element, then delete the last element.

2. To achieve O(1) lookup of which server id to remove in the arraylist,

store a server id to arraylist index mapping in the hashmap.

 

 
 1 public class LoadBalancer {
 2     private HashMap<Integer, Integer> map;
 3     private ArrayList<Integer> list;
 4     private Random rand;
 5     public LoadBalancer() {
 6         this.map = new HashMap<Integer, Integer>();
 7         this.list = new ArrayList<Integer>();
 8         this.rand = new Random();
 9     }
10 
11     // @param server_id add a new server to the cluster 
12     // @return void
13     public void add(int server_id) {
14         if(!map.containsKey(server_id)){
15             list.add(server_id);
16             map.put(server_id, list.size() - 1);    
17         }
18     }
19 
20     // @param server_id server_id remove a bad server from the cluster
21     // @return void
22     public void remove(int server_id) {
23         if(map.containsKey(server_id)){
24             int removeIdx = map.get(server_id);
25             map.remove(server_id);
26             int affectedServerId = list.get(list.size() - 1);
27             map.put(affectedServerId, removeIdx);
28             list.set(removeIdx, affectedServerId);
29             list.remove(list.size() - 1);
30         }
31     }
32 
33     // @return pick a server in the cluster randomly with equal probability
34     public int pick() {
35         if(list.size() == 0){
36             return -1;
37         }
38         int rand_idx = rand.nextInt(list.size());
39         return list.get(rand_idx);
40     } 
41 }

 

 

 

 

转载于:https://www.cnblogs.com/lz87/p/7203653.html

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值