1)多線程方式利用多核心
鎖(信號量、互斥鎖、自旋鎖、讀寫鎖、原子鎖cas、樂觀鎖、悲觀鎖)
鎖的粒度
什麼狀況下用什麼鎖,比較困惑
react
消息隊列linux
管道(不須要加鎖): pipe+epoll/select/epollnginx
資源+鎖redis
併發實體:線程sql
總結:
須要大量的鎖。
docker
2)多進程方式利用多核心
共享內存
數據庫
pipe管道、
父進程fork子進程有限制
只能一端讀一端寫
數據是單向的
編程
socket:
通常用這種來
用epoll
數組
信號網絡
併發實體:進程。
總結:
3)csp模型
go語言:
併發實體:goroutine(協程,用channel來通訊)。
協程是輕量級的線程。
協程切換比較輕量,是開發者本身調度的。
線程切換須要進程,進程切換須要。
總結:
優化多線程的編程方式。
4)actor
erlang:
語言層面實現actor模型。
把actor命名爲進程,actor是輕量級的進程。
skynet:
從框架層面實現actor。
actor由程序來調度,比較輕量。
提幾個問題:
1.actor之間是如何溝通的?
統一性差,隔離性強。
獨立的運行環境。
a actor和b actor溝通,就發送到對方的消息隊列中。
多進程是socket溝通,其實也是消息的方式。
2.actor是怎麼運行的?
多進程中,有一個主線程,經過os調度來運行。
actor中,當消息隊列中有消息的時候,就能夠運行:
多個線程,消耗actor消息。 工做線程。輪訓,消息隊列取出消息,並在actor
環境中運行了。
取出消息,而且調用回調函數。
3.actor是如何調度的呢?
不是每一個actor都有消息。這個怎麼處理呢?
全局消息隊列。把actor中的消息插入全局消息隊列,指針的方式。
經過多線程消費全局消息隊列的方式來調度actor,這樣範圍縮小,效率提升。
將有消息的消息隊列放入全局消息隊列中,工做線程只須要輪訓全局消息隊列,
就能夠對整個actor消息進行調度了。
4.actor怎麼接收網絡中的數據?
fd和actor綁定
epoll_create
紅黑樹+就緒隊列
epoll_ctrl
epoll_event, fd, actor_id
epoll_wait(ev[])
取出一個數組
ev[].data.ptr -->actorid, fd--》找到actor--》網絡線程發送數據到actor
5.如何使用skynet?
agent--》玩家actor
hall--》大廳actor
main--》啓動actor
redis---》玩家不能退出,從新進去要保存數據。 redis actor
room--》房間actor,3人一個房間組成的actor
./skynet/skynet config.test
main
redis
hall
把功能拆分紅多個actor, 熱點拆分爲多個actor,
一個actor就是一個統一性較差的環境。
架構:
main:網關--》listenfd
agent: connedfd--》其它數據所有由agent進行處理
遊戲是相同的,咱們不能放到一個actor中處理,而要建立不少個節點,充分利用cpu
每個client都有一個agent
hall:保存匹配隊列的--》大廳
每個agent與hall鏈接
hall去建立一個room actor
skynet中的2種調用方式:
send:消息隊列send,異步調用。
call--》rpc: 阻塞,同步調用。
指導思想: 簡單可用,逐步優化,忌諱過分優化
邏輯的完備性
actor:
隔離的環境(lua或內存塊)
回調函數
消息隊列
單線程來處理的
讓工做線程去輪訓只有消息的actor
總結:
優化的是多進程的解決方案。
---------------------------
併發編程的2個考慮:
隔離性
運行環境隔離:
多線程隔離性差、統一性高
統一性
數據的統一
------------------------------
分佈式:
C:一致性
A:可用性
P:分區容錯性
----------------------
源碼:
nginx
redis
skynet
zeromq
造輪子:
中間件:
內存池
線程池
鏈接池
消息隊列
高併發IO:
epoll
reactor
proactor
網絡協議棧:
用戶態,實現百萬鏈接
nginx模塊開發
併發設計
集羣能力:
數據庫的集羣。
zookeeper的集羣--》多進程的管理。
linux內核編程:
網卡子系統的編程
內存管理
進程間通訊
內核的編譯
性能測試:
數據庫的索引優化和sql優化。
linux調優、內存調優。
部署能力:
docker
一線架構