Article-No.05 大型网站系统与Java中间件实践

1、阿姆达尔定律:S(N) = 1/(1-P) + P/N

P:程序中并行部分的程序在单核上执行时间的占比

N:处理器的个数(总核心数)

S(N):程序在N个处理器(总核心数)相对于单个处理器(单核)中的速度提升比

总结:这个公式告诉我们,在程序中可并行代码的比例决定你增加处理器所能带来的速度的提升的上限

2、ConcurrentHashMap:支持并发效率更高的Map

    如果只调用get()方法或者put()方法,ConcurrentHashMap是线程安全的,但是如果你调用get()方法后,又调用put()方法,如果有另外一个线程在当前线程调用put()返回之前调用,很可能会把之前的操作覆盖掉,很多情况下一个业务会涉及容器的多个操作,即复合操作,并发执行时,线程安全的容器只能保证自身的数据不被破坏,但无法保证业务的行为是否正确。

private final Map<String, Long> wordCounts = new ConcurrentHashMap<>();
/**
 *如果多个线程并发调用这个increase()方法,increase()的实现就是错误的,因为多个线程用相同的word调用时,很可能会覆盖相互的结果,造成记录的次数比实际出现的次数少。
*/
public long increase(String word) {
    Long oldValue = wordCounts.get(word);
    Long newValue = (oldValue == null) ? 1L : oldValue + 1;
    wordCounts.put(word, newValue);
    return newValue;
}

//putIfAbsent方法,如果key/value存在,则返回value,如果不存在返回null;replace如果新值和旧值相同,则返回false,反之则返回true
public long increase(String word) {
    Long oldValue, newValue;
    while (true) {
        oldValue = wordCounts.get(word);
        if (oldValue == null) {
            // Add the word firstly, initial the value as 1
            newValue = 1L;
            if (wordCounts.putIfAbsent(word, newValue) == null) {
                break;
            }
        } else {
            newValue = oldValue + 1;
            if (wordCounts.replace(word, oldValue, newValue)) {
                break;
            }
        }
    }
    return newValue;
}

//改进
public long increase(String word) {
    AtomicLong number = wordCounts.get(word);
    if (number == null) {
        AtomicLong newNumber = new AtomicLong(0);
        number = wordCounts.putIfAbsent(word, newNumber);
        if (number == null) {
            number = newNumber;
        }
    }
    return number.incrementAndGet();
}

3、避免死锁的方式:原子性的获取需要的多个锁或注意调整对多个锁的获取顺序

4、服务器负载均衡的几种方式

    1)硬件负载均衡:中间代理转发

    2)LVS/Nginx软件负载均衡:中间代理转发

    3)名称服务:请求服务先访问名称服务器,获取处理服务器ip或域名列表并返回,请求服务器按照一定的规则进行负载选择请求的服务器地址

    4)规则服务:请求服务访问规则服务器,获取规则算法并返回,请求服务器按照规则计算进行负载

    5)Master-Worker服务器

5、解决应用服务器变为集群后的Session问题

    web服务器是我们每天要去吃饭的饭店,session会话数据是我们吃饭用的碗筷,目标是保证每次吃饭都用自己的碗筷

    1)Session Sticky:保证同一个会话的请求都在同一个web服务器上处理,需要在负载均衡上做选择,可以进行一致性hash实现。把碗筷放在某一家饭店里,每次都去那家饭店吃饭。

    2)Session Replication(session复制):多台服务器之间实现session的同步操作。每一家饭店都放了一份自己的碗筷,这样无论去哪家都可以用自己的碗筷。

    3)Session集中存储:session数据集中存储在一个session集群中,所有对session读写操作都在在这个session集群中处理。将碗筷统一的放在一起,每次吃饭都先去那把碗筷拿着,吃饭了再放回去。

    4)Cookie Based:将session数据保存在cookie中,每次发生请求的时候coookie中都带有session的数据,可以对session进行加密处理。每次都把自己的碗筷带在身上,这样每次去任何一家饭店吃饭都用自己的碗筷。

6、数据库瓶颈解决

    1)主从式读写分离

    2)站内搜索引擎,相当于一个读库

    3)缓存:数据缓存、页面缓存

    4)分布式页面系统、分布式存储系统、分布式数据库系统

    5)数据库垂直拆分(专库专用、按照页面不同表分在不同数据库中),水平拆分(单张表记录达到临界值,将一张表拆分成多张表放在不同数据库中)

7、

你可能感兴趣的:(Article-No.05 大型网站系统与Java中间件实践)