winform 线程监听两个目录下的文件_vb.net 利用.net自带的GZipStream压缩或者解压文件的代码,不需要任何第三方控件...
網上很少有用VB寫的壓縮文件的代碼,但是,在網絡傳輸,文件下載,打包發布等等方面的需求又比較多,所以,借鑒了一下C#代碼的例子,改造成了VB用的類。另外加上了多層文件夾壓縮解壓。但是,因為時間有限,只是將文件全部讀取到緩存處理,所以,針對大文件沒有做特別的處理。例子里面有提示,根據需要自己改動一下吧。
文件:n459.com/file/25127180-478678624
以下內容無關:
-------------------------------------------分割線---------------------------------------------
在日常開發中,為了保證數據的一致性,我們一般都選擇關系型數據庫來存儲數據,如 MySQL,Oracle 等,因為關系型數據庫有著事務的特性。然而在并發量比較大的業務場景,關系型數據庫卻又往往會成為系統瓶頸,無法完全滿足我們的需求,所以就需要使用到緩存,而非關系型數據庫,即 NoSQL 數據庫往往又會成為最佳選擇。
NoSQL 數據庫最常見的解釋是 non-relational,也有人解釋為 Not Only SQL。非關系型數據庫不保證事務,也就是不具備事務 ACID 特性,這也是非關系型數據庫和關系型數據庫最大的區別,而我們即將介紹的 Redis 就屬于 NoSQL 數據庫的一種。
什么是 Redis
Redis 全稱是:REmote DIctionary Service,即遠程字典服務。Redis 是一個開源的(遵守 BSD 協議)、支持網絡、可基于內存亦可持久化的日志型、Key-Value 數據庫。Redis 具有以下特性:
- 1、支持豐富的數據類型:字符串(strings),散列(hashes),列表(lists),集合(sets),有序集合(sorted sets),位圖等。
- 2、功能豐富:提供了持久化機制,過期策略,訂閱/發布等功能。
- 3、高性能,高可用且支持集群。
- 4、提供了多種語言的 API。
Redis 的安裝
- 1、下載對應版本的安裝包,如:Redis 5.0.5 版本,其他版本也可以點擊這里進行下載。
- 2、下載好之后傳到服務器指定目錄,執行命令 tar -zxvf redis-5.0.5.tar.gz 進行解壓。
- 3、解壓成功之后,進入 Redis 主目錄,執行命令 make && make install PREFIX=/xxx/xxx/redis-5.0.5 進行安裝,如果不指定目錄,則默認是安裝在 /usr/local 目錄下。
- 4、安裝成功之后可以看到 Redis 主目錄下多了一個 bin 目錄,bin 目錄內包含了一些可執行腳本。
- 5、回到 Redis 主目錄下,找到 redis.conf 配置文件,將其中的配置 daemonize no 修改為 daemonize yes,表示在后臺啟動服務。
- 6、然后就可以執行命令 /xxx/xxx/redis-5.0.5/bin/redis-server /xxx/xxx/redis-5.0.5/redis.conf 啟動 Redis 服務。
Redis 到底有多快
大家可能都知道 Redis 很快,可是 Redis 到底能有多快呢,比如 Redis 的吞吐量能達到多少?我想這就不是每一個人都能說的上來一個具體的數字了。
Redis 官方提供了一個測試腳本,可以供我們測試 Redis 的 吞吐量。
- redis-benchmark -q -n 100000 可以測試常用命令的吞吐量。
- redis-benchmark -t set,lpush -n 100000 -q 測試 Redis 處理 set 和 lpush 命令的吞吐量。
- redis-benchmark -n 100000 -q script load "redis.call('set','foo','bar')" 測試 Redis 處理 Lua 腳本等吞吐量。
下圖就是我這邊執行第一條命令的自測結果,可以看到大部分命令的吞吐量都可以達到 4 萬以上,也就是說每秒鐘可以處理 4 萬次以上請求:
但是如果你以為這就是 Redis 的真實吞吐量,那就錯了。實際上,Redis 官方的測試結果是可以達到 10 萬的吞吐量,下圖就是官方提供的一個基準測試結果(縱坐標就是吞吐量,橫坐標是連接數):
Redis 是單線程還是多線程
這個問題比較經典,因為在很多人的認知里,Redis 就是單線程的。然而 Redis 從 4.0 版本開始就有了多線程的概念,雖然處理命令請求的核心模塊確實是保證了單線程執行,然而在其他許多地方已經有了多線程,比如:在后臺刪除對象,通過 Redis 模塊實現阻塞命令,生成 dump 文件,以及 6.0 版本中網絡 I/O 實現了多線程等,而且在未來 Redis 應該會有越來越多的模塊實現多線程。
所謂的單線程,只是說 Redis 的處理客戶端的請求(即執行命令)時,是單線程去執行的,并不是說整個 Redis 都是單線程。
Redis 為什么選擇使用單線程來執行請求
Redis 為什么會選擇使用單線程呢?這是因為 CPU 成為 Redis 瓶頸的情況并不常見,成為 Redis 瓶頸的通常是內存或網絡帶寬。例如,在一個普通的 Linux 系統上使用 pipelining 命令,Redis 可以每秒完成 100 萬個請求,所以如果我們的應用程序主要使用 O(N) 或 O(log(N)) 復雜度的命令,它幾乎不會使用太多的 CPU。
那么既然 CPU 不會成為瓶頸,理所當然的就沒必要去使用多線程來執行命令,我們需要明確的一個問題就是多線程一定比單線程快嗎?答案是不一定。因為多線程也是有代價的,最直接的兩個代價就是線程的創建和銷毀線程(當然可以通過線程池來一定程度的減少頻繁的創建線程和銷毀線程)以及線程的上下文切換。
在我們的日常系統中,主要可以區分為兩種:CPU 密集型 和 IO 密集型。
- CPU 密集型:這種系統就說明 CPU 的利用率很高,那么使用多線程反而會增加上下文切換而帶來額外的開銷,所以使用多線程效率可能會不升反降。舉個例子:假如你現在在干活,你一直不停的在做一件事,需要 1 分鐘可以做完,但是你中途總是被人打斷,需要花 1 秒鐘時間步行到旁邊去做另一件事,假如這件事也需要 1 分鐘,那么你因為反復切換做兩件事,每切換一次就要花 1 秒鐘,最后做完這 2 件事的時間肯定大于 2 分鐘(取決于中途切換的次數),但是如果中途不被打斷,你做完一件事再去做另一件事,那么你最多只需要切換 1 次,也就是 2 分 1 秒就能做完。
- IO 密集型:IO 操作也可以分為磁盤 IO 和網絡 IO 等操作。大部分 IO 操作的特點是比較耗時且 CPU 利用率不高,所以 Redis 6.0 版本網絡 IO 會改進為多線程。至于磁盤 IO,因為 Redis 中的數據都存儲在內存(也可以持久化),所以并不會過多的涉及到磁盤操作。舉個例子:假如你現在給樹苗澆水,你每澆完一次水之后就需要等別人給你加水之后你才能繼續澆,那么假如這個等待過程需要 5 秒鐘,也就是說你澆完一次水就可以休息 5 秒鐘,而你切換去做另一件事來回只需要 2 秒,那么你完全可以先去做另一件事,做完之后再回來,這樣就可以充分利用你空閑的 5 秒鐘時間,從而提升了效率。
使用多線程還會帶來一個問題就是數據的安全性,所以多線程編程都會涉及到鎖競爭,由此也會帶來額外的開銷。
什么是 I/O 多路復用
I/O 指的是網絡 I/O, 多路指的是多個 TCP 連接(如 Socket),復用指的是復用一個或多個線程。I/O 多路復用的核心原理就是不再由應用程序自己來監聽連接,而是由服務器內核替應用程序監聽。
在 Redis 中,其多路復用有多種實現,如:select,epoll,evport,kqueue 等。
我們用去餐廳吃飯為的例子來解釋一下 I/O 多路復用機制(點餐人相當于客戶端,餐廳的廚房相當于服務器,廚師就是線程)。
- 阻塞 IO:張三去餐廳吃飯,點了一道菜,這時候他啥事也不干了,就是一直等,等到廚師炒好菜,他就把菜端走開始吃飯了。也就是在菜被炒好之前,張三被阻塞了,這就是 BIO(阻塞 IO),效率會非常低下。
- 非阻塞 IO:張三去餐廳吃飯,點了一道菜,這時候張三他不會一直等,找了個位置坐下,刷刷抖音,打打電話,做點其他事,然后每隔一段時間就去廚房問一下自己的菜好了沒有。這種就屬于非阻塞 IO,這種方式雖然可以提高性能,但是如果有大量 IO 都來定期輪詢,也會給服務器造成非常大的負擔。
- 事件驅動機制:張三去餐廳吃飯,點了一道菜,這時候他找了個位置坐下來等:
- 廚房那邊菜做好了就會把菜端出來了,但是并不知道這道菜是誰的,于是就挨個詢問顧客,這就是多路復用中的 select 模型,不過 select 模型最多只能監聽 1024 個 socket(poll 模型解決了這個限制問題)。
- 廚房做好了菜直接把菜放在窗口上,大喊一聲,某某菜做好了,是誰的快過來拿,這時候聽到通知的人就會自己去拿,這就是多路復用中的 epoll 模型。
需要注意的是在 IO 多路復用機制下,客戶端可以阻塞也可以選擇不阻塞(大部分場景下是阻塞 IO),這個要具體情況具體分析,但是在多路復用機制下,服務端就可以通過多線程(上面示例中可以多幾個廚師同時炒菜)來提升并發效率。
Redis 中 I/O 多路復用的應用
Redis 服務器是一個事件驅動程序,服務器需要處理兩類事件:文件事件和時間事件。
- 文件事件:Redis 服務器和客戶端(或其他服務器)進行通信會產生相應的文件事件,然后服務器通過監聽并處理這些事件來完成一系列的通信操作。
- 時間事件:Redis 內部的一些在給定時間之內需要進行的操作。
Redis 的文件事件處理器以單線程的方式運行,其內部使用了 I/O 多路復用程序來同時監聽多個套接字(Socket)連接,提升了性能的同時又保持了內部單線程設計的簡單性。下圖就是文件事件處理器的示意圖:
I/O 多路復用程序雖然會同時監聽多個 Socket 連接,但是其會將監聽的 Socket 都放到一個隊列里面,然后通過這個隊列有序的,同步的將每個 Socket 對應的事件傳送給文件事件分派器,再由文件事件分派器分派給對應的事件處理器進行處理,只有當一個 Socket 所對應的事件被處理完畢之后,I/O多路復用程序才會繼續向文件事件分派器傳送下一個 Socket 所對應的事件,這也可以驗證上面的結論,處理客戶端的命令請求是單線程的方式逐個處理,但是事件處理器內并不是只有一個線程。
Redis 為什么這么快
Redis 為什么這么快的原因前面已經基本提到了,現在我們再進行總結一下:
- 1、Redis 是一款純內存結構,避免了磁盤 I/O 等耗時操作。
- 2、Redis 命令處理的核心模塊為單線程,減少了鎖競爭,以及頻繁創建線程和銷毀線程的代價,減少了線程上下文切換的消耗。
- 3、采用了 I/O 多路復用機制,大大提升了并發效率。
總結
以上是生活随笔為你收集整理的winform 线程监听两个目录下的文件_vb.net 利用.net自带的GZipStream压缩或者解压文件的代码,不需要任何第三方控件...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql 1005 - can't c
- 下一篇: 控制dcom程序使用端口_使用VS Co