輕量級數據庫中間件利器Sharding-JDBC深度解析(有彩蛋)

講師介紹



640.png?wxfrom=5&wx_lazy=1

張亮

當當架構部總監


  • 負責分布式中間件和私有云平臺建設

  • 目前主導開源項目:Elastic-Job及Sharding-JDBC?



主題簡介:

1、關系型數據庫中間件核心功能介紹

2、Sharding-JDBC架構及內核解析

3、Sharding-JDBC未來展望


一、關系型數據庫中間件核心功能介紹


關系型數據庫憑借靈活查詢的SQL和穩定的存儲及事務引擎,一直以來是業務存儲領域的首選。而在規模越來越大的互聯網年代,單一的關系型數據庫卻已難滿足需求。開發人員不愿放棄SQL查詢的靈活度及對之前代碼的兼容性,而又無法承受數據量過大時所帶來的性能瓶頸。因此NoSQL和NewSQL分別產生,而NoSQL的不兼容性和NewSQL的不成熟,也使得關系型數據庫仍將長期存在下去。所以,繼續使用關系型數據庫,并能解決互聯網規模所帶來的沖擊,數據庫中間層這個既不保守,也不激進的平衡方案被大多數互聯網公司所接受。關系型數據庫中間件采用單體向分布式透明轉化的方案來解決數據量和訪問量巨大這兩個互聯網場景的核心問題。


關系型數據庫在大于自身數據量閥值的情況下,性能會急劇下降。在面對互聯網海量數據情況時,所有數據都存于單表,顯然會輕易超過數據庫表可承受的范圍。這個單表可承受的數據量閥值,需根據數據庫和并發量的差異,通過實際測試獲得。


通過分庫和分表拆分數據來使得各個表的數據量保持在閥值以下。拆分方式為垂直拆分和水平拆分。垂直拆分是根據業務將單庫(表)拆分為多庫(表)。如:將常用的字段和不常用的字段拆分至不同的庫(表)中。但垂直拆分需要對架構和設計進行調整,往往來不及應對互聯網業務需求的快速變化,而且也并不能真正的解決單點瓶頸。水平拆分則是根據分片算法將一個庫(表)拆分為多個庫(表)。如:根據ID的最后一位以10取余,尾數是0的放入0庫(表),尾數是1的放入1庫(表)。水平拆分從理論上突破了單機數據量處理的瓶頸,并且擴展相對自由,是分庫分表的標準解決方案。


分庫和讀寫分離疏導流量是應對高訪問量的常見手段。分表雖然可以解決海量數據導致的性能問題,但無法解決過多請求訪問同一數據庫,導致其響應變慢的問題。所以水平拆分通常要采取分庫的方式,一并解決數據量和訪問量巨大的問題。讀寫分離是另一個疏導流量的辦法,但讀寫數據間的延遲是架構設計時需要考慮的問題。

?

雖然分庫可以解決上述問題,但分布式架構在獲得了收益的同時,也帶來了新的問題。


跨庫事務是分布式數據庫要面對的棘手事情。合理采用分表,可以在降低單表數據量的情況下,盡量使用本地事務,善于使用同庫不同表可有效避免分布式事務帶來的麻煩。在不能避免跨庫事務的場景,有些業務仍然需要保持事務的一致性。而基于XA的分布式事務由于性能低下,無法被互聯網公司所采納,它們大多采用最終一致性的柔性事務代替分布式事務。


因此,最佳實踐是合理地配合使用分庫+分表。在實現上,分表的難度遠大于分庫,它需要對SQL解析,并且對表名改寫,而分庫則不需要。

?

另一個分布式衍生的問題是主鍵生成。它必須可以保證分布式唯一。分布式主鍵的生成方式分為中心化和去中心化兩大類。中心化可以繼續采用數據庫生成自增主鍵的方式,為每個不同的分庫設置不同的初始值,并將步長設置為分片的個數即可,這種方式對分片個數有依賴,一旦再次水平擴展,原有的分布式主鍵不易遷移。還有一種中心化生成分布式主鍵的方式,即采用Redis在內存中生成自增序列,但此種方式新增加了一個外部組件的依賴,一旦Redis不可用,則整個數據庫將無法在插入,可用性會大大下降,另外Redis的單點問題也需要解決,部署復雜度較高。去中心化方式無需額外部署,可擴展性也很好,因此更推薦使用。UUID是去中心化生成分布式主鍵較為常見的一種方式,但它的主鍵很長,而且無序,通過主鍵排序時對數據庫的性能影響較大,不建議使用。目前較為完美的方案是使用snowflake算法生成分布式唯一和基本有序的主鍵。

?

綜上所述,分布式數據庫中間件的功能模塊非常清晰,有其存在的必要和市場價值。但與旺盛的需求形成鮮明對比,成熟的關系型數據庫中間件鳳毛麟角。主要原因是各公司均開發各自的中間件,沒有形成統一的標準及規范,也沒有動力從公司現有的系統中解耦并獨立開源。當當同樣自研,并決定將其開源,命名為Sharding-JDBC。從2016年開源至今,已發布了15個版本,其中包含5個里程碑版本升級。在經歷了整體架構的數次精煉以及穩定性打磨后,如今它已積累了足夠的底蘊,相信可以成為開發者選擇技術組件時的一個參考。


二、Sharding-JDBC架構及內核解析


Sharding-JDBC完整的實現了分庫分表,讀寫分離和分布式主鍵功能,并初步實現了柔性事務。


它直接實現JDBC接口,舊代碼遷移成本幾乎為零,可適用于任何基于Java的ORM框架,如:JPA、Hibernate、Mybatis、SpringJDBC Template等;理論上可以支持所有實現JDBC協議的數據庫,但由于各種數據庫的SQL方言差別較大,每種SQL都需要獨立的解析器,Sharding-JDBC目前僅支持MySQL、PostgreSQL、Oracle和SQL Server這4種最主流的數據庫。由于柔性事務與JDBC沒有直接關系,因此正在考慮將它拆分為一個獨立的項目。


Sharding-JDBC與基于MySQL等數據庫協議實現的Proxy中間層在部署架構上差別很大,但在代碼的核心邏輯上差別并不大。Sharding-JDBC作為lib庫,是與業務代碼部署在一起的,而基于Proxy的中間層則是架在數據庫的前方,與應用代碼在部署上隔絕。無論使用哪種架構,它們的核心邏輯均極為相似,都會分為分片規則配置、SQL解析、SQL路由、SQL改寫、SQL執行以及結果歸并模塊,區別僅在于協議實現層的不同(JDBC或數據庫協議)。


Sharding-JDBC架構圖如下:

640?wxfrom=5&wx_lazy=1


左邊部分是部署架構圖,右邊部分則是核心邏輯架構圖。

?

使用Sharding-JDBC,性能是大家最關心的問題。


在數據量一致的情況下,使用Sharding-JDBC和原生JDBC的性能測試報告如下:

  • 查詢操作:Sharding-JDBC的TPS為JDBC的TPS的99.8%。

  • 插入操作:Sharding-JDBC的TPS為JDBC的TPS的90.2%。

  • 更新操作:Sharding-JDBC的TPS為JDBC的TPS的93.1%。

  • 可以看到,Sharding-JDBC在查詢中的性能損失非常低,插入和更新略高。

?

將單表的數據拆分為二,放入兩個表中,使用Sharding-JDBC和原生JDBC的性能測試報告如下:

  • 查詢操作:TPS雙庫比單庫可以增加大約94%的性能。

  • 插入操作:TPS雙庫比單庫可以增加大約60%的性能。

  • 更新操作:TPS雙庫比單庫可以增加大約89%的性能。

  • 結果表明,Sharding-JDBC可有效利用水平擴展大幅度提升性能。

?

下面我將按照模塊深度剖析Sharding-JDBC的詳細功能和主要實現,請大家和我一起探索與評估它的水有多深。


分片規則配置


Sharding-JDBC的分片策略配置是自定義的,因此可以通過編程的方式最大限度的靈活調整。它并不僅支持=運算符分片,可支持BETWEEN和IN的運算符分片,支持將一條邏輯SQL最終散落至多個數據節點。同時支持多分片鍵,例如:根據用戶ID分庫,訂單ID分表這種分庫分表結合的分片策略;或根據年分庫,月份+用戶區域ID分表這樣的多片鍵分片。


通過編程的方式定制分片規則雖然靈活,但配置起來略顯繁瑣。因此Sharding-JDBC又提供了Inline表達式編寫分片策略的方式,用于配置集中化,以避免配置散落在配置文件和代碼中的情況。此外,它還提供了定制化的Spring命名空間和YAML進一步簡化配置。


JDBC規范重寫


Sharding-JDBC對JDBC規范的重寫思路是針對DataSource、Connection、Statement、PreparedStatement和ResultSet這5個核心接口封裝,將多個實現類集合納入Sharding-JDBC實現類管理。分布式主鍵也屬于JDBC協議的一部分。


Sharding-JDBC盡量最大化實現JDBC協議,但分布式畢竟與原生JDBC不同,所以目前仍有未實現的接口,包括游標,存儲過程、SavePoint以及向前遍歷和修改ResultSet等不太常用的功能。此外,為了保證兼容性,并未實現JDBC 4.1及其后發布的接口(如:DBCP 1.x版本不支持JDBC 4.1)。


SQL解析


SQL解析作為分庫分表類產品的核心,性能和兼容性是最重要的衡量指標。目前常見的SQL解析器主要有fdb,jsqlparser和Druid。Sharding-JDBC1.4.x之前的版本使用Druid作為SQL解析器,經實際測試,它的性能遠超其它解析器。

從1.5.x版本開始,Sharding-JDBC采用完全自研的SQL解析引擎。由于目的不同,它并不需要將SQL轉為AST語法樹,也無需通過Visitor的方式二次遍歷。它采用對SQL“半理解”的方式,僅提煉分片需要關注的上下文,因此SQL解析的性能和容錯性得到了進一步的提高。


SQL解析模塊由Lexer和Parser兩個模塊組成。Lexer用于將SQL拆解為Token,并將其歸類為關鍵詞,表達式,字面量和操作符。Parser則用于理解SQL和提煉分片上下文,并標記可能需要改寫的位置。分片上下文包含SELECTItems、表信息、分片條件、自增主鍵信息、排序信息、分組信息和Limit信息。一次解析過程是不可逆的,一個個Token的依次解析,因此解析性能很高。由于各種數據庫的SQL差異很大,因此在解析模塊對每種數據庫提供方言的支持。


Sharding-JDBC支持各種連接、聚合、排序、分組以及分頁的解析,并且可以有限度的支持子查詢。


SQL路由


SQL路由是根據分片規則配置以及解析上下文中的分片條件,將SQL定位至真正的數據源。它又分為直接路由、簡單路由和笛卡爾積路由。


滿足直接路由的條件比較苛刻,如果通過Hint(通過HintAPI直接指定路由至庫表)方式分片,且僅分庫,則無需SQL解析和結果歸并。因此它的SQL兼容性最好,可以執行包括子查詢、OR、UNION等復雜情況的任意SQL。


簡單路由是Sharding-JDBC最推薦使用的分片方式,它是指不包含JOIN或僅包含Binding表JOIN的SQL。Binding表是指使用同樣的分片鍵和分片規則的一組表,也就是說任何情況下,Binding表的分片結果應與主表一致。例如:order表和order_item表,都根據order_id分片,結果應是order_1與order_item_1成對出現。這樣的關聯查詢和單表查詢復雜度和性能相當。如果分片條件不是等于,而是BETWEEN或IN,則路由結果不一定落入單庫(表),因此一條邏輯SQL最終可能拆分為多條SQL語句。


笛卡爾積查詢最為復雜,因為無法根據Binding關系定位分片規則的一致性,所以非Binding表的關聯查詢需要拆解為笛卡爾積組合執行。查詢性能較低,而且數據庫連接數較高,需謹慎使用。


SQL改寫


SQL改寫模塊的用途是將邏輯SQL改寫為可以分布式執行的SQL。在Sharding-JDBC 1.5.x版本,SQL改寫進行了調整和大量優化。1.4.x及之前版本,SQL改寫是在SQL路由之前完成的,在1.5.x中調整為SQL路由之后,因為SQL改寫可以根據路由至單庫表還是多庫表而進行進一步優化。SQL改寫分為正確性改寫和優化改寫兩部分。


正確性改寫包括將分表的邏輯表名稱替換為真實表名稱,修正分頁信息和增加補列。舉兩個例子:


  • AVG計算。分布式場景,以avg1 + avg2 + avg3 / 3計算平均值并不正確,需要改寫為 (sum1 + sum2 + sum3) ?/ (count1 + count2 + count3)。這就需要將包含AVG的SQL改寫為SUM和COUNT,并在結果歸并時重新計算平均值。


  • 分頁。假設每10條數據為一頁,取第2頁數據。在分片環境下獲取LIMIT 10, 10,歸并之后再根據排序條件取出前10條數據是不正確的結果。正確的做法是將分條件改寫為LIMIT 0, 20,取出所有前兩頁數據,再結合排序條件計算出正確的數據。因此越是獲取靠后數據,分頁的效率就會越低。有很多方法可避免使用LIMIT進行分頁。比如構建記錄行記錄數和行偏移量的二級索引,或使用上次分頁數據結尾ID作為下次查詢條件的分頁方式。


優化改寫是1.5.x重點提升的部分,實現的功能比較零散,這里同樣舉兩個例子:


  • 單路由拒絕改寫。這是將SQL改寫挪到SQL路由之后的原因。當獲得路由結果之后,單路由的情況因為不涉及到結果歸并,因此分頁、補列等改寫都無需存在。尤其是分頁,無需將數據從第1條開始取,節省了網絡帶寬。


  • 流式歸并改寫。一會講到歸并時會說,這里先提一句,將僅包含GROUPBY的SQL改寫為GROUPBY + ORDERBY。


SQL執行


路由至真實數據源后,Sharding -JDBC將采用多線程并發執行SQL。它用3種執行引擎分別對應處理Statement,PreparedStatement和AddBatchPreparedStatement。Sharding-JDBC線程池放在一個名為ShardingContext的對象中,它的生命周期同ShardingDataSource保持一致。如果一個應用中創建了多個Sharding-JDBC的數據源,它們將持有不同的線程池。



結果歸并



Sharding-JDBC支持的結果歸并從功能上分為遍歷、排序、分組和分頁4種類型,它們是組合而非互斥的關系。從結構劃分,可分為流式歸并、內存歸并和裝飾者歸并。流式歸并和內存歸并是互斥的,裝飾者歸并可以在流式歸并和內存歸并之上做進一步的處理。


流式歸并是將數據游標與結果集的游標保持一致,順序的從結果集中一條條的獲取正確的數據。遍歷和排序都是流式歸并,分組比較復雜,分為流式分組和內存分組。內存歸并則是需要將結果集的所有數據都遍歷并存儲在內存中,再通過內存歸并后,將內存中的數據偽裝成結果集返回。


遍歷類型最為簡單,只需將多結果集組成鏈表,遍歷完成當前結果集后,將鏈表位置后移,繼續遍歷下一個結果集即可。


排序類型稍微復雜,由于ORDER BY的原因,每個結果集自身數據是有序的,因此只需要將結果集當前游標指向的值排序即可。Sharding-JDBC在排序類型歸并時,將每個結果集的當前排序數據實現了比較器,并將其放入優先級隊列。每次JDBC調用next時,將隊列頂端的結果集出隊并next,然后獲取新的隊列頂端的結果集供JDBC獲取數據。


分組類型最為復雜,分組歸并已經不屬于OLTP范疇,而更面向OLAP,但由于遺留系統使用很多,因此Sharding-JDBC還是將其實現。分組歸并分成流式分組歸并和內存分組歸并。流式分組歸并節省內存,但必須要求排序和分組的數據保持一致。如果GROUPBY和ORDER BY的內容不一致,則必須使用內存分組歸并。由于數據不是按照分組需要的順序取出,因此需要將結果集中的所有數據全部加載至內存。在SQL改寫時提到的僅有GROUP BY的SQL,會優化增加ORDER BY語句,即使將內存分組歸并優化為流式分組歸并的提升。


無論是流式分組還是內存分組,對聚合的處理都是一致的。聚合分為比較、累加和平均值3種類型。比較聚合包括MAX和MIN,只返回最大(小)結果。累加聚合包括SUM和COUNT,需要將結果累加后返回。平均值聚合則是通過SQL改寫的SUM和COUNT計算,相關內容已在SQL改寫涵蓋,不再贅述。

最后再聊一下裝飾者歸并,他是對所有的結果集歸并進行統一的功能增強,目前裝飾者歸并只有分頁一種類型。


上述的所有歸并類型,都可能分頁或不分頁,因此可以通過裝飾者模式來增加分頁的能力。分頁歸并會將改寫的LIMIT中,不需要獲取的數據過濾掉。Sharding-JDBC的分頁很容易產生誤解,很多人認為分頁會占用大量內存,因為Sharding-JDBC會因為分布式正確性的考量,將LIMIT 100000, 10改寫為LIMIT 0, 100010,產生Sharding-JDBC會將100010數據都加載到內存的錯覺。通過上面分析可知,會全部加載到內存的只有內存分組歸并這一種情況。其他情況都是通過流式獲取結果集數據的方式,因此Sharding-JDBC會通過結果集的next方法將無需取出的數據全部跳過,并不會將其存入內存。


分布式主鍵


分布式主鍵在這里單獨提煉出一個章節,因為它是貫穿于Sharding-JDBC整個生命周期的。


分布式主鍵最獨立的部分是生成策略,Sharding-JDBC提供靈活的配置分布式主鍵生成策略方式。在分片規則配置模塊可配置每個表的主鍵生成策略,默認使用snowflake。


通過策略生成的分布式主鍵可以無縫的融入JDBC協議,它實現了Statement的getGeneratedKeys方法,將其返回改寫后的Result和ResultMetaData,將Sharding-JDBC生成的分布式主鍵偽裝為數據庫生成的自增主鍵返回。


SQL解析時,需要根據分布式主鍵配置策略判斷是否在邏輯SQL中已包含主鍵列,如果未包含則需要將INSERTItems和INSERT Values的最后位置寫入解析上下文。


SQL改寫時,將根據解析上下文中的位置改寫SQL,增加未包含的主鍵列名稱和值。如果是Statement則在INSERT Values后追加生成后的分布式主鍵;如果是PreparedStatement則在INSERT Values后追加?,并在傳入的參數后追加生成后的分布式主鍵。


受限于篇幅,讀寫分離、柔性事務就不在此說明了。


三、Sharding-JDBC未來展望


首先,請和我一同回顧下Sharding-JDBC每個里程碑版本的歷程。


1.0.x:分庫分表

1.1.x:配置簡易化

1.2.x:柔性事務

1.3.x:讀寫分離

1.4.x:分布式主鍵

1.5.x:自研解析引擎 + 多數據庫支持

?

通過這5個版本的迭代可以看到,Sharding-JDBC的精力主要集中在透明化分布式數據庫這部分,因此經常有人問Sharding-JDBC和基于Proxy的數據庫中間層有什么區別?和NewSQL數據庫又有什么區別?


盡管部署架構不同,但功能上確實差異不明顯。不過結構的不同終會將它們推向不同的方向。Sharding-JDBC與業務代碼部署在一起的架構,非常適合作為微服務的數據訪問層基礎開發組件。Proxy和NewSQL是面向運維的數據庫,而Sharding-JDBC的定位與當當一并開源的DubboX、Elastic-Job一樣,是面向開發的微服務基礎類庫,它始終以云原生的基礎開發套件為目標。


Sharding-JDBC 1.6.x到來,將會愈加明顯的劃清界限。Sharding-JDBC 1.6.x的目標是配置動態化和數據庫治理,通過將配置存入注冊中心,達到治理分庫分表+讀寫分離的數據庫的目的。在應用端進行數據庫發現、流量疏導、故障轉移、熔斷等功能,向治理服務一樣治理數據庫。


Sharding-JDBC將作為面向OLTP在線業務的分片化的數據庫治理微服務基礎組件積極的發展下去。真誠邀請感興趣的人關注和參與。


來源:中生代技術

原文鏈接

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/394673.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/394673.shtml
英文地址,請注明出處:http://en.pswp.cn/news/394673.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python字典嵌套字典的情況下獲取某個key的value

最近在用python寫接口的測試程序,期間用到解析字典獲取某個key的value,由于多個接口返回的字典格式不是固定的并存在多層嵌套的情況。在字典的方法中也沒有找到可直接達到目的的方法(也可能是我對字典的方法了解的不深的緣故),于是自己寫了個…

系統在此應用程序堆棧溢出_從部署我的第一個完整堆棧Web應用程序中學到的經驗教訓...

系統在此應用程序堆棧溢出by Will Abramson威爾艾布拉姆森(Will Abramson) 從部署我的第一個完整堆棧Web應用程序中學到的經驗教訓 (Lessons learned from deploying my first full-stack web application) I recently achieved one of my long-term goals: deploying my firs…

const 常量_條款03:盡可能使用const

const 允許你指定一個語義約束(也就是指定一個“不該被改動”的對象),而編譯器會強制實施這項約束。1、const指針如果關鍵字const出現在星號左邊,表示被指物是常量;如果出現在星號右邊,表示指針自身是常量&…

javascript高級程序設計---js事件思維導圖

繪制思維軟件與平時用的筆記,以及導出功能,這三個問題綜合起來,于是我把思維導圖分開畫 1、js事件的基本概念 2、js事件的事件處理程序 3、js事件的事件對象 轉載于:https://www.cnblogs.com/Jamie1032797633/p/10567419.html

jq挑戰30天——打字機效果+小程序

<!doctype html><html><head><meta charset"utf-8"><title>基于jQuery實現的打字機效果-jq22.com</title><script src"http://libs.baidu.com/jquery/1.11.3/jquery.min.js"></script><style></…

和 Thrift 的一場美麗邂逅

一. 與 Thrift 的初識 也許大多數人接觸 Thrift 是從序列化開始的。每次搜索 “java序列化” “方式”、“對比” 或 “性能” 等關鍵字時&#xff0c;搜索引擎總是會返回一大堆有關各種序列化方式的使用方法或者性能對比的結果給你&#xff0c;而其中必定少不了 Thrift&#…

instagram技術_Instagram9位科技女孩進行技術采訪的主要技巧

instagram技術by Rachel通過瑞秋 Instagram9位科技女孩進行技術采訪的主要技巧 (Top tips for technical interviews from nine of Instagram’s tech girls) My job-hunt came to an end a few weeks ago. After endless phone interviews, coding challenges, and on-sites,…

彈出框 每次打開 滾動條置頂_微信置頂文字怎么弄?微信置頂一句話教程

今日支付寶紅包支付寶首頁搜索511501453馬上領取紅包(支付寶雙十二活動&#xff0c;瓜分15億紅包)(領取后一定要記得使用&#xff0c;不然會浪費的呦&#xff0c;更會影響第二天的領取&#xff01;)奶思靚機“ 一 個 有 用 的 公 眾 號 の ”嗨&#xff0c;最近很流行在微信上面…

Python學習_字符串格式化

#!/usr/bin/env python # -*- coding:utf-8 -*-# 百分號格式化 # %[(name)[flags][width].[precision]]typecode # name : 指定占位符的key # flags : - 空格 0 # width : 寬度 # precision : 小數點后保留的位數 # typecode : 必需,數據類型 # 字符串里面有%的時候, %%表示一…

python 3 面向過程編程

python 3 面向過程編程 核心是過程&#xff08;流水線式思維&#xff09;&#xff0c;過程即解決問題的步驟&#xff0c;面向過程的設計就像設計好一條工業流水線&#xff0c;是一種機械式的思維方式。 1、優點&#xff1a;程序結構清晰&#xff0c;可以把復雜的問題簡單化&…

在ionic/cordova中使用百度地圖插件

在ionic項目中&#xff0c;如果想實現定位功能&#xff0c;可以使用ng-cordova提供的cordova-plugin-geolocation。 但由于高墻的緣故&#xff0c;國內andorid環境下&#xff0c;此插件不起作用&#xff08;ios環境下可用&#xff09;。 國內比較好的是現實使用百度地圖提供的A…

django國際化與html語言,Django 國際化

Django 國際化Django 支持國際化&#xff0c;多語言。Django的國際化是默認開啟的&#xff0c;如果您不需要國際化支持&#xff0c;那么您可以在您的設置文件中設置 USE_I18N False&#xff0c;那么Django會進行一些優化&#xff0c;不加載國際化支持機制。NOTE: 18表示Intern…

mongo 刪除節點_將生產節點/ Express Mongo App部署到AWS —反思

mongo 刪除節點在AWS中部署生產Web應用程序的經驗教訓 (Lessons learned deploying a production web application in AWS) 背景 (Background) This is not a code-based tutorial. It consists of all the things I wish I knew before I started the project and the steps I…

漢諾塔問題遞歸算法python代碼_[python]漢諾塔問題遞歸實現

一、問題描述及算法步驟 漢諾塔問題的大意是有三根柱子a, b, c&#xff0c;現在a柱有N個盤子從下往上尺寸遞減排列&#xff0c;要求&#xff1a; 1. 將a上的盤子移動到c柱上; 2. 每次移動一個盤子; 3. 柱子上的盤子始終必須是大的在下面image.png 漢諾塔問題的經典實現算法步驟…

【硬件】PCB設計步驟

前言 合理的PCB設計步驟&#xff0c;可以減少反復修改的可能性。動手設計PCB前&#xff0c;需要按步就班準備一些資料&#xff0c;即使是小項目。 本文將講解如何一次性成功地設計一款PCB的常規步驟。 當然&#xff0c;如果是一個系統&#xff0c;則需要按照瀑布式的思路&#…

linux install StarDict

1.  sudo apt-get install stardict 2.  Downloads from: http://abloz.com/huzheng/stardict-dic/zh_CN/ 3.  tar jxf stardict-21shijishuangxiangcidian-2.4.2.tar.bz2 -C /usr/share/stardict/dic (etc other dictionaries)轉載于:https://www.cnblogs.com/HurryXin/…

交付方式 saas_我在全職工作時如何交付我的第一個SaaS副項目

交付方式 saasby Tigran Hakobyan由Tigran Hakobyan 我在全職工作時如何交付我的第一個SaaS副項目 (How I shipped my first SaaS side-project while working full-time) This is my personal story of how I shipped my very first SaaS side-project while working full-ti…

nginx搭建基于http協議的視頻點播服務器

1&#xff0c;于由自己的服務器上已經安裝好nginx(具體安裝方法見我的另一篇文章&#xff0c;Linux中安裝nginx)&#xff0c;所以不再安裝。 2&#xff0c;下載nginx_mod_h264_streaming-2.2.7.tar.gz(自己在網上搜吧)。 3&#xff0c;安裝pcre&#xff0c;先看有沒有安裝。 [r…

plsql 批量調存儲過程_數控雙端開榫機:批量銑榫頭真牛氣

數控雙端開榫機主要用于實木家具批量化銑榫頭專用&#xff0c;因為其本身的優勢逐漸被家具廠老板們所接受&#xff0c;是目前家具生產不可缺少的一款自動化設備&#xff0c;給企業節約了生產成本&#xff0c;今天又焦峰小編來給大家講解一下。主要技術參數&#xff1a;知乎視頻…

c 向html頁面傳值,html頁面之間的傳值,獲取元素和方法的調用

這篇文章是自己在項目中遇到&#xff0c;同時參考了網上的資料&#xff0c;作為筆記參考使用一、頁面之間的傳值1、使用cookie傳值封裝簡單使用&#xff1a;//獲取cookiefunction getCookie(name){var arr,regnew RegExp("(^| )"name"([^;]*)(;|$)");if(ar…