知名虐機頻道評選 2020 年智慧型手機耐用獎,誰是最堅固的贏家?_貨運

※智慧手機時代的來臨,RWD網頁設計為架站首選

網動結合了許多網際網路業界的菁英共同研發簡單易操作的架站工具,及時性的更新,為客戶創造出更多的網路商機。

虐機,大概是所有消費者最感興趣的話題,哪一款手機最耐用、哪一款手機耐用性最差,還有更深奧的那些手機最容易被修復等。知名虐機頻道 JerryRigEverything 更是相當有名的其中翹楚,只要提到虐機就絕對不能沒有看過這頻道,近日該頻道評選出 2020 年的各種智慧型手機耐用性獎項,分享給大家一看。

知名虐機頻道評選 2020 年智慧型手機耐用獎,誰是最堅固的贏家?

要說專業拆機,大家會想到的 iFixit,如果講到專業虐機,那當然非 JerryRigEverything 莫屬。在2020 年裡面,該頻道虐盡市面上的主流機型,並且在豐富的經驗累積之下評選出 2020 年的各得獎者,接下來就來為大家列出到底有哪些獎項,又有哪些機型獲選為該獎項的得獎者吧!

(點選後面機型可前往查看虐機影片)

可維修性最高:Google Pixel 5
可維修性最低:黑鯊 3
最具創新性機型:ZTE Axon 20
榮譽獎:LG Wing
內部結構最好看的機型:iPhone 12 Pro Max
耐用性最差手機:OnePlus Nord
最讓人迷惑的手機:Google Pixel 5
耐用性最佳手機:Google Pixel 4a

從 2016 年開始,該頻道每年都會將虐過的手機整理起來,在看似無目的的破壞同時了解各手機的耐用度,並且在隔年初進行最終評分,讓大家都能了解過去這一年裡面哪些手機最是頭好壯壯。下面就與大家分享完整版的影片(前半段大概講了投入各種公益,還有自家買了什麼東西…)。

※回頭車貨運收費標準

宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念

當然這裡被列入的機型都是比較大眾化、一般消費型手機,所以那些本來就是特定職業人士或專門設計在嚴峻環境中所使用的三防手機自然不在其中。

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

※評比南投搬家公司費用收費行情懶人包大公開

搬家價格與搬家費用透明合理,不亂收費。本公司提供下列三種搬家計費方案,由資深專業組長到府估價,替客戶量身規劃選擇最經濟節省的計費方式

小米11 Lite 通過 FCC 認證,相關規格提前曝光!_包裝設計

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

小米除了「數字旗艦」之外,近年也會針對年輕族群等相對輕量使用需求推出系列的 Lite 青春版,近期也有款疑似為小米11 系列的新機通過 FCC 認證,也讓部份規格提前曝光。這款傳聞為小米 11 Lite 的新機預計配備 6GB RAM 和 128GB ROM ,內建 4250mAh 大電量電池且支持最高 33W 有線快充。

▲圖片來源:The Pixel(YouTube)

小米11 Lite 通過 FCC 認證,相關規格提前曝光!

雖然,目前還不確定小米11 未來是否有機會、何時才會引進台灣銷售,不過最近傳出小米11 系列除了預期在農曆新年後登場的小米11 Pro 旗艦,還可能會推出一款相較「輕量」的小米11 Lite 。最近隨著 FCC 認證通過的文件曝光,也有更多關於小米11 Lite 的規格傳聞陸續曝光。

▲圖片來源:The Pixel(YouTube)

根據 FCC 等認證的文件可確認,這款型號 M210K9AG 的小米新機全系列皆配備 6GB RAM ,儲存空間分為 64GB 和 128GB 兩種容量選擇。

▲圖片來源:FCC

而小米11 Lite 預計是款 4G 手機,傳聞將搭載 Qualcomm Snapdragon 732G 處理器:

▲圖片來源:FCC

電池容量方面,小米11 Lite 將內建 4250mAh 大電量電池,同時也支持最高 33W 的有線快充:

這項消息也與數碼閒聊站在微博的爆料吻合,而數碼閒聊站也提到小米11 Lite 將從上一代的水滴螢幕升級成單挖孔螢幕:

▲圖片來源:數碼閒聊站(微博)

也有 YouTube 頻道「The Pixel」分享小米11 Lite 的外觀渲染圖,小米11 可能採取單挖孔螢幕將前置鏡頭設計在螢幕左上角,且螢幕可能支持最高 120Hz 更新率:

▲圖片來源:The Pixel(YouTube)

▲圖片來源:The Pixel(YouTube)

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

雖然關於小米11 Lite 的相機規格目前未有太多的消息,不過傳聞將比照小米11 的設計風格並配備 6400 萬像素的三鏡頭主相機。

▲圖片來源:The Pixel(YouTube)

消息來源:FCC

延伸閱讀:
realme V15 正式發表:176 克輕盈重量、50W 智慧閃充並標配 65W 閃充充電器,售價僅約 6,450 元起

小米11 官方拆解影片釋出,輕薄機身如何收納 S888 處理器、Harman Kardon 調音立體雙揚聲器?透過影片快速揭秘

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

讀懂操作系統之虛擬內存地址翻譯原理分析篇(二)_網頁設計公司

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。

前言

上一節我們整體概括通過MMU將虛擬地址翻譯為物理地址的轉換,這個過程都是按序就班的進行,一切都是基於已提前創建、分配虛擬頁、物理頁以及命中的前提,只是給和我一樣沒怎麼系統學習操作系統的童鞋首先在腦海里有個大概的印象,本節我們從源頭開始分析為程序創建進程到映射到主存上整個詳細過程,本文將通過大量圖解來分析原理,以便讓各位能夠完全理解地址翻譯原理。若有敘述不當之處,還請批評指正。 

虛擬內存原理分析

如果沒有系統學習現代操作系統,理論上我們會認為用戶程序會將內存視為單個連續的內存空間,實際上可以將用戶程序在內存中分佈可以分散在頁面的整個物理內存中。分頁是一種內存管理方案,它允許進程的物理地址空間不連續。

物理內存劃分:將物理內存劃分為稱為幀的固定大小的塊(大小為2的冪,介於512字節和16 MB之間,必須跟蹤所有空閑幀)

虛擬(邏輯)內存劃分:將邏輯內存分成大小相同的塊(稱為頁,每一塊也是分為相同大小的頁面)

若要運行大小為N頁的程序,需要找到N個空閑幀並加載程序

地址翻譯方案

通過常駐內存中的頁表將虛擬地址翻譯為物理地址, CPU生成的虛擬地址被劃分為虛擬頁號(用作頁表索引,該頁表包含物理內存中每個頁的基地址)和虛擬頁偏移量(與基址結合找到存儲單元的物理存儲地址)。對於給定的邏輯地址空間2m和頁面大小2n,如下:

分頁內存管理方案本質就是通過MMU將CPU產生的虛擬地址通過中間媒介(頁表)進行地址翻譯,如下為簡單翻譯版本,一目瞭然。

上述我們學習了將邏輯地址(虛擬地址)劃分為頁號(注意:頁號並不屬於頁表的一部分,頁號不儲存在主存)和頁偏移量,到底是怎樣藉助頁號和頁偏移量進行翻譯的呢?我們舉個例子:假設如下一個32字節的物理內存,邏輯地址空間為16字節,說明邏輯地址有4位,而頁幀偏移量為4個字節,因頁幀偏移量和虛擬頁偏移量相等,所以虛擬頁偏移量也為4個字節即2位,所以頁號為(4-2)= 2位即邏輯地址共有4頁,如此假設和實際理論計算對等。地址翻譯如下:

若CPU要找出邏輯地址為4的物理地址,通過上述我們知道邏輯地址為4在第1頁且偏移量為0,然後去查找頁表索引等於1的頁幀號為6,因為物理地址 = (frame * pageSize)+ offset,所以邏輯地址4的物理地址=(6 * 4 bytes)+ 0 byte offset = 24。同理,比如如上邏輯地址為7在第1頁,偏移量為3對應頁表上的幀6,所以其物理地址為:(6 * 4 bytes)+ 3 byte offset = 27,這裏需要注意的是物理地址的偏移量是相對這頁的起始位置偏移。通過上述圖解,我們反推根據邏輯地址和每頁字節大小計算出其所在頁和偏移量(下面根據虛擬地址計算虛擬頁號和偏移量會用到),比如邏輯地址為7,因每頁大小為4個字節,則所在頁為(7 / 4) = 1,偏移量(7 mod / 4) = 3。

擴展頁表條目(PTE)信息

現代計算機頁表上的條目除了包含將虛擬地址翻譯為虛擬地址的主要信息(有效位、頁號)外,其中還包含如下其他信息(下面講解頁面置換算法會用到):

保護位(Protection):控制對指定虛擬頁的訪問是否可讀、可寫、可執行

引用位(Refrence):為了近似實現LRU算法,幫助操作系統估算最近最少使用的頁,當一頁被訪問時該位將被置位,操作系統定期將引用位清零,然後重新記錄,這樣就可以判定在這段特定時間內哪些頁被訪問過,通過檢查引用位是否關閉,操作系統就可以從那些最近最少訪問的頁中選擇一頁

臟位(Modify):當某一頁被替換時,操作系統需要知道該頁是否需要被複制寫回,為了追蹤讀入主存中的頁是否被寫過,增加一個臟位,當頁中任何字被寫時就將這一位置位。如果操作系統選擇替換某一頁,臟位指明了把該頁所佔用的主存讓給另一頁之前,是否需要將該頁寫回磁盤,因此,一個被修改的頁通常被稱為臟頁。

TLB緩存頁表

上一節我們講過CPU產生邏輯地址后通過MMU轉換為物理地址時,每次都要訪問頁表,訪問緩存和主存的時間相差上百個時鐘周期,所以為了提高查找性能則使用TLB,我們可認為TLB是實現頁表最好的方式,本質上是緩存頁表。在沒有TLB作為緩存時,我們使用頁號(VPN)作為索引去頁表上查找物理頁號,引入TLB后,將頁號劃分為TLBT(TLB標記)和TLBI(TLB索引)只是做了一下轉換而已,TLBI佔2位,剩餘的位就是TLBT。下面會通過一個實際例子來講解如何結合TLBT和TLBI在TLB上查找。

 

TLB作為頁表的緩存,用於存放映射到頁幀中的那些項,TLB包含了頁表中虛擬頁到頁幀映射的一個子集,因為將其作為緩存,所以額外還存在如上一個標記區域(TLBT),換句話說頁表不同於TLB並不是作為緩存,所以並不需要標記區域,再加上如上額外的PTE擴展信息,所以TLB的存儲結構如下:

TLB缺失

接下來我們開始進入TLB缺失環節,我們假設虛擬地址有14位,物理地址有16位,每頁大小有64個字節,那麼虛擬地址空間和物理地址空間如下圖所示

因為每頁大小為64字節即(26),同時虛擬頁偏移量和頁幀偏移量相等,所以虛擬頁偏移量和頁幀偏移量都為6位,那麼將虛擬地址空間和物理地址空間劃分為對應的頁號和頁偏移量則如下圖所示:

接下來則是將虛擬頁號劃分為TLBT和TLBI,因為TLB包含16個條目且4路關聯,那麼說明有S =(16 / 4)= 4組,那麼TLBI佔位 =  log2S = 2,剩餘的則是TLBT = (8 – 2) = 6位,如下圖所示

現在我們對虛擬地址和物理地址都有了完整的劃分,現在假設TLB和頁表狀態存儲結構分別如下圖

 

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境

假設現在CPU產生一個虛擬地址(0x0334),首先我們需要將其轉換為虛擬頁號(VPN),因每個頁面大小為64字節,所以計算方式如下代碼

var xvpn = Convert.ToInt32("0x334", 16);
var vpn = xvpn / 64; //vpn = 12
var vpo = xvpn % 64; //vpo = 52

上述計算出VPN等於12,然後將其對應虛擬地址上的VPN和VPO用二進製表示,分別如下圖所示

而存儲在TLB和頁表上的狀態都是16進制,所以上述VPN = 1210 = 0x0C16和VPO = 5210 = 0x3416,到此已經劃分完VPN和VPO,接下來則是將VPN劃分為TLBT和TLBI,由上述我們已經知道TLBT和TLBI在VPN中所佔位數,所以如下圖所示

由上我們可得出TLBT = 310 = 0x0316,而TLBI = 0,有了TLBT(0x03)和TLBI(0)再去查找TLB狀態表,如下紅色標記

由上圖我們發現此時標誌無效而且物理頁號也沒有,此時發生TLB缺失,於是通過MMU將虛擬地址得到的VPN去頁表中查找

此時我們看到在頁表中也缺失,所以這裏將發生缺頁異常。TLB缺失分為如下兩種情況

頁在主存(頁表)中,只需要創建缺失的TLB表項

頁不在主存(頁表)中,需要將控制權交給操作系統來解決缺頁 

TLB缺失既可以通過軟件處理也可以通過硬件處理,比如MIPS、Alpha通過軟件處理TLB缺失,x86、ARM通過硬件處理TLB缺失,兩種處理方式在性能差別上很小,無論哪一種方式需要執行的基本操作都是一樣的。理論上來講,在進程分配頁幀時會將對應頁幀更新到頁表上,但是上述情況並未在主存頁表中說明在頁幀列表中沒有空閑的頁幀,所以這是TLB缺失中真正的缺頁情況,此時將觸發缺頁異常,控制權交給操作系統內核中的缺頁異常處理程序,操作系統知道了引起缺頁的虛擬地址,操作系統必須完成以下3個步驟:【1】使用虛擬地址查找頁表項,並在磁盤上找到被訪問的頁的位置【2】選擇替換一個物理頁,如果該選中的頁被修改過,需要在把新的虛擬頁裝入之前將這個物理頁寫回磁盤,這一過程稱為頁面置換【3】啟動讀操作,將被訪問的頁從磁盤上取回到所選擇的物理頁的位置上【4】重新執行引發缺頁的那條指令。因為第3個步驟需要耗費數百萬個時鐘周期,如果第2個步驟中被替換的物理頁已被重寫過,那麼同樣也會花費這麼長時間,因此操作系統會選擇另外一個進程在處理器上執行直到磁盤訪問結束,所以前3個步驟執行所耗費的時間比較長,最後重新執行缺頁指令。若在頁表中找到了頁幀號(即頁在主存中),那說明TLB缺失只是一次轉換缺失,在這種情況下,CPU只需要將頁表項裝載到TLB並且重新訪問來進行缺失處理。

頁面置換算法

為了解決缺頁情況,所以必須實現頁面置換作為請求調頁的基礎,這裏我們介紹常見的幾種置換算法,分別是Optional or MIN algorithm、FIFO(First-In-First-Out)、Clock、LRU(Least Recently Used),針對各個算法,現假設有(1、2、3、4、1、2、5、1、2、3、4、5)12個引用串,4個空閑頁幀。

FIFO(先進先出)

該算法記錄了每個頁面記錄調到內存的時間,當必須置換頁面時,將選擇最舊的頁面,請注意,並不需要記錄調入頁面的確切時間,可以通過創建一個隊列實現此目的。具體過程太過簡單,這裏就不再細講,此時將發生10次缺頁錯誤,我們可計算出缺頁率為(10/12)= 83%。如下:

 

OPT or MIN(最優)

最優置換算法找出最長時間沒有使用的頁,具有最低缺頁率,可以用作離線分析方法,但是難以實現。此時將發生6次缺頁錯誤,我們可計算出缺頁率為(6/12)= 50%。如下:

 

LRU(最近最少使用)

FIFO算法使用的是頁面調入內存的時間,OPT算法使用的是頁面將來使用的時間,而LRU算法採用置換最長時間沒有的頁,該算法將每個頁面與它上次使用的時間關聯起來,當需要置換頁面時,LRU選擇最長時間沒有使用的頁面,該算法很難實現。此時將發生8次缺頁錯誤,我們可計算出缺頁率為(8/12)= 67%。如下:

啟動和切換進程

上述我們只是從已經將程序加載到內存中所創建的進程角度來分析如何將虛擬地址翻譯為物理地址,由於操作系統負責管理內存,因此必須了解物理內存的分配詳細信息,分配了哪些頁幀、每個頁幀分配個哪個進程的哪個頁面,哪些頁幀可用,總共有多少幀,對此我們還一無所知。將用戶程序加載到虛擬內存中的進程後為其劃分對應的虛擬頁,假設如下劃分了4個虛擬頁,操作系統在跟蹤的頁幀列表找出空閑(操作系統分配幀算法,這裏暫不討論)的頁幀分配給虛擬頁,然後操作系統再啟動進程。如下圖:

 

如上節所述頁表保存在主存中,當調度進程時通過頁表基址寄存器(PTBR)指向激活的指定進程頁表, 當然也會加載另外一個寄存器(程序計數器,PC),所以每個數據或指令訪問需要進行兩次主存訪問,一次是頁表,另一次則是用於數據或指令。

 

當進程希望以受限的方式共享信息時,操作系統必須對其進行協助,這是因為訪問另外一個進程的信息需要改變訪問進程的頁表,寫訪問位可以用來把共享限製為只讀,並且和頁表中其他位一樣,該位只能被操作系統所修改。為了允許另一進程,設為P1,去讀屬於進程P2的一頁,P2就要請求操作系統在P1地址空間中為一個虛擬頁生成頁表項,指向P2想要共享的物理頁。如果P2要求操作系統可以使用寫保護位以防止P1對數據進行改寫,由於只有TLB缺失才會訪問頁表,任何決定頁對的訪問權限不僅要包含在頁表中,還要包含在TLB中。當操作系統決定從進程P1切換到P2時,我們稱之為上下文切換,它必須保證P2不能P1的頁表,否則不利於數據保護,若沒有TLB,只需要把頁表基址寄存器指向P2的頁表而不是P1就夠了,如果有TLB,我們必須在其中清除屬於P1的表項,不僅僅是為了保護P1的數據,而且是為了迫使TLB裝入P2的表項。如果進程切換的頻率很高,那麼這一舉措效率將會很低。例如,在操作系統切回P1之前,P2可能只裝入了很少的TLB表項,但是,P1隨後發現它所有的表項都不見了,因此不得不通過TLB缺失來重新加載這些表項,產生這個問題的原因在於進程P1和P2使用同一虛擬地址空間,並且我們必須清除TLB以防止地址混淆。另一種常見的方法則是增加進程標識符和任務標識符來擴展虛擬地址空間,比如FastMATH就有8位地址空間標識域(ASID),這個標識域標識了當前正在運行的進程,當進程切換時,它保存在由操作系統裝入的寄存器中,進程標識符與TLB的標記部分相連接,因此只有在頁號和進程標識符相匹配時,TLB才會發生命中,如此一來,除非特殊情況,我們就不需要清除TLB。 說了怎麼多除了保護機制外,當我們切換進程時主要需要做哪些工作呢(即從一個進程控制塊(Process Control Block,PCB)切換到另一個進程塊,後續會深入講解操作系統線程和進程)?

切換頁表到當前PCB

頁表基址寄存器指向當前頁表

清除TLB,並將當前頁表項裝載到TLB(按需加載,進程訪問哪些頁才將對應頁表項加載到TLB)

留個作業

若TLB中的PTE條目達到上限即滿時,不難想象理論上會替換現有條目,那麼採取替換的策略或機制是怎樣的呢?

總結

基於上一節內容我們詳細講解了將虛擬地址翻譯為物理地址的具體過程、進程頁幀分配、頁面置換算法,在講解TLB缺失時並未涉及高速緩存,TLB和高速緩存將在下一節作為詳解。關於虛擬內存內容通過一兩篇文章根本講解不清楚,比如還有減少頁表容量方式、TLB和高速緩存關係、Intel和Linux虛擬內存系統等等。我盡量通過圖解方式來帶給大家較好的理解體驗,能夠更好的消化和吸收虛擬內存。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。

基於 abp vNext 和 .NET Core 開發博客項目 – 博客接口實戰篇(一)_網頁設計公司

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

透過資料庫的網站架設建置,建立公司的形象或購物系統,並提供最人性化的使用介面,讓使用者能即時接收到相關的資訊

系列文章

  1. 基於 abp vNext 和 .NET Core 開發博客項目 – 使用 abp cli 搭建項目
  2. 基於 abp vNext 和 .NET Core 開發博客項目 – 給項目瘦身,讓它跑起來
  3. 基於 abp vNext 和 .NET Core 開發博客項目 – 完善與美化,Swagger登場
  4. 基於 abp vNext 和 .NET Core 開發博客項目 – 數據訪問和代碼優先
  5. 基於 abp vNext 和 .NET Core 開發博客項目 – 自定義倉儲之增刪改查
  6. 基於 abp vNext 和 .NET Core 開發博客項目 – 統一規範API,包裝返回模型
  7. 基於 abp vNext 和 .NET Core 開發博客項目 – 再說Swagger,分組、描述、小綠鎖
  8. 基於 abp vNext 和 .NET Core 開發博客項目 – 接入GitHub,用JWT保護你的API
  9. 基於 abp vNext 和 .NET Core 開發博客項目 – 異常處理和日誌記錄
  10. 基於 abp vNext 和 .NET Core 開發博客項目 – 使用Redis緩存數據
  11. 基於 abp vNext 和 .NET Core 開發博客項目 – 集成Hangfire實現定時任務處理
  12. 基於 abp vNext 和 .NET Core 開發博客項目 – 用AutoMapper搞定對象映射
  13. 基於 abp vNext 和 .NET Core 開發博客項目 – 定時任務最佳實戰(一)
  14. 基於 abp vNext 和 .NET Core 開發博客項目 – 定時任務最佳實戰(二)
  15. 基於 abp vNext 和 .NET Core 開發博客項目 – 定時任務最佳實戰(三)
  16. 基於 abp vNext 和 .NET Core 開發博客項目 – 博客接口實戰篇(一)
  17. 基於 abp vNext 和 .NET Core 開發博客項目 – 博客接口實戰篇(二)
  18. 基於 abp vNext 和 .NET Core 開發博客項目 – 博客接口實戰篇(三)
  19. 基於 abp vNext 和 .NET Core 開發博客項目 – 博客接口實戰篇(四)
  20. 基於 abp vNext 和 .NET Core 開發博客項目 – 博客接口實戰篇(五)
  21. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(一)
  22. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(二)
  23. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(三)
  24. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(四)
  25. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(五)
  26. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(六)
  27. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(七)
  28. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(八)
  29. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(九)
  30. 基於 abp vNext 和 .NET Core 開發博客項目 – 終結篇之發布項目

從本篇就開始博客頁面的接口開發了,其實這些接口我是不想用文字來描述的,太枯燥太無趣了。全是CRUD,誰還不會啊,用得着我來講嗎?想想為了不半途而廢,為了之前立的Flag,還是咬牙堅持吧。

準備工作

現在博客數據庫中的數據是比較混亂的,為了看起來像那麼回事,顯得正式一點,我先手動搞點數據進去。

搞定了種子數據,就可以去愉快的寫接口了,我這裏將根據我現在的博客頁面去分析所需要接口,感興趣的去點點。

為了讓接口看起來清晰,一目瞭然,刪掉之前在IBlogService中添加的所有接口,將5個自定義倉儲全部添加至BlogService中,然後用partial修飾。

//IBlogService.cs
public partial interface IBlogService
{
}

//BlogService.cs
using Meowv.Blog.Application.Caching.Blog;
using Meowv.Blog.Domain.Blog.Repositories;

namespace Meowv.Blog.Application.Blog.Impl
{
    public partial class BlogService : ServiceBase, IBlogService
    {
        private readonly IBlogCacheService _blogCacheService;
        private readonly IPostRepository _postRepository;
        private readonly ICategoryRepository _categoryRepository;
        private readonly ITagRepository _tagRepository;
        private readonly IPostTagRepository _postTagRepository;
        private readonly IFriendLinkRepository _friendLinksRepository;

        public BlogService(IBlogCacheService blogCacheService,
                           IPostRepository postRepository,
                           ICategoryRepository categoryRepository,
                           ITagRepository tagRepository,
                           IPostTagRepository postTagRepository,
                           IFriendLinkRepository friendLinksRepository)
        {
            _blogCacheService = blogCacheService;
            _postRepository = postRepository;
            _categoryRepository = categoryRepository;
            _tagRepository = tagRepository;
            _postTagRepository = postTagRepository;
            _friendLinksRepository = friendLinksRepository;
        }
    }
}

在Blog文件夾下依次添加接口:IBlogService.Post.csIBlogService.Category.csIBlogService.Tag.csIBlogService.FriendLink.csIBlogService.Admin.cs

在Blog/Impl文件夾下添加實現類:IBlogService.Post.csBlogService.Category.csBlogService.Tag.csBlogService.FriendLink.csBlogService.Admin.cs

同上,.Application.Caching層也按照這個樣子添加。

注意都需要添加partial修飾為局部的接口和實現類,所有文章相關的接口放在IBlogService.Post.cs中,分類放在IBlogService.Category.cs,標籤放在IBlogService.Tag.cs,友鏈放在IBlogService.FriendLink.cs,後台增刪改所有接口放在IBlogService.Admin.cs,最終效果圖如下:

文章列表頁

分析:列錶帶分頁,以文章發表的年份分組,所需字段:標題、鏈接、時間、年份。

.Application.Contracts層Blog文件夾下添加返回的模型:QueryPostDto.cs

//QueryPostDto.cs
using System.Collections.Generic;

namespace Meowv.Blog.Application.Contracts.Blog
{
    public class QueryPostDto
    {
        /// <summary>
        /// 年份
        /// </summary>
        public int Year { get; set; }

        /// <summary>
        /// Posts
        /// </summary>
        public IEnumerable<PostBriefDto> Posts { get; set; }
    }
}

模型為一個年份和一個文章列表,文章列表模型:PostBriefDto.cs

//PostBriefDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{
    public class PostBriefDto
    {
        /// <summary>
        /// 標題
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// 鏈接
        /// </summary>
        public string Url { get; set; }

        /// <summary>
        /// 年份
        /// </summary>
        public int Year { get; set; }

        /// <summary>
        /// 創建時間
        /// </summary>
        public string CreationTime { get; set; }
    }
}

搞定,因為返回時間為英文格式,所以CreationTime 給了字符串類型。

IBlogService.Post.cs中添加接口分頁查詢文章列表QueryPostsAsync,肯定需要接受倆參數分頁頁碼和分頁數量。還是去添加一個公共模型PagingInput吧,在.Application.Contracts下面。

//PagingInput.cs
using System.ComponentModel.DataAnnotations;

namespace Meowv.Blog.Application.Contracts
{
    /// <summary>
    /// 分頁輸入參數
    /// </summary>
    public class PagingInput
    {
        /// <summary>
        /// 頁碼
        /// </summary>
        [Range(1, int.MaxValue)]
        public int Page { get; set; } = 1;

        /// <summary>
        /// 限制條數
        /// </summary>
        [Range(10, 30)]
        public int Limit { get; set; } = 10;
    }
}

Page設置默認值為1,Limit設置默認值為10,Range Attribute設置參數可輸入大小限制,於是這個分頁查詢文章列表的接口就是這個樣子的。

//IBlogService.Post.cs
public partial interface IBlogService
{
    /// <summary>
    /// 分頁查詢文章列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    Task<ServiceResult<PagedList<QueryPostDto>>> QueryPostsAsync(PagingInput input);
}

ServiceResultPagedList是之前添加的統一返回模型,緊接着就去添加一個分頁查詢文章列表緩存接口,和上面是對應的。

//IBlogCacheService.Post.cs
using Meowv.Blog.Application.Contracts;
using Meowv.Blog.Application.Contracts.Blog;
using Meowv.Blog.ToolKits.Base;
using System;
using System.Threading.Tasks;

namespace Meowv.Blog.Application.Caching.Blog
{
    public partial interface IBlogCacheService
    {
        /// <summary>
        /// 分頁查詢文章列表
        /// </summary>
        /// <param name="input"></param>
        /// <param name="factory"></param>
        /// <returns></returns>
        Task<ServiceResult<PagedList<QueryPostDto>>> QueryPostsAsync(PagingInput input, Func<Task<ServiceResult<PagedList<QueryPostDto>>>> factory);
    }
}

分別實現這兩個接口。

//BlogCacheService.Post.cs
public partial class BlogCacheService
{
    private const string KEY_QueryPosts = "Blog:Post:QueryPosts-{0}-{1}";

    /// <summary>
    /// 分頁查詢文章列表
    /// </summary>
    /// <param name="input"></param>
    /// <param name="factory"></param>
    /// <returns></returns>
    public async Task<ServiceResult<PagedList<QueryPostDto>>> QueryPostsAsync(PagingInput input, Func<Task<ServiceResult<PagedList<QueryPostDto>>>> factory)
    {
        return await Cache.GetOrAddAsync(KEY_QueryPosts.FormatWith(input.Page, input.Limit), factory, CacheStrategy.ONE_DAY);
    }
}
//BlogService.Post.cs
/// <summary>
/// 分頁查詢文章列表
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public async Task<ServiceResult<PagedList<QueryPostDto>>> QueryPostsAsync(PagingInput input)
{
    return await _blogCacheService.QueryPostsAsync(input, async () =>
    {
        var result = new ServiceResult<PagedList<QueryPostDto>>();

        var count = await _postRepository.GetCountAsync();

        var list = _postRepository.OrderByDescending(x => x.CreationTime)
                                  .PageByIndex(input.Page, input.Limit)
                                  .Select(x => new PostBriefDto
                                  {
                                      Title = x.Title,
                                      Url = x.Url,
                                      Year = x.CreationTime.Year,
                                      CreationTime = x.CreationTime.TryToDateTime()
                                  }).GroupBy(x => x.Year)
                                  .Select(x => new QueryPostDto
                                  {
                                      Year = x.Key,
                                      Posts = x.ToList()
                                  }).ToList();

        result.IsSuccess(new PagedList<QueryPostDto>(count.TryToInt(), list));
        return result;
    });
}

PageByIndex(...)TryToDateTime().ToolKits層添加的擴展方法,先查詢總數,然後根據時間倒序,分頁,篩選出所需字段,根據年份分組,輸出,結束。

BlogController中添加API。

/// <summary>
/// 分頁查詢文章列表
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpGet]
[Route("posts")]
public async Task<ServiceResult<PagedList<QueryPostDto>>> QueryPostsAsync([FromQuery] PagingInput input)
{
    return await _blogService.QueryPostsAsync(input);
}

[FromQuery]設置input為從URL進行查詢參數,編譯運行看效果。

※想知道最厲害的網頁設計公司嚨底家"!

RWD(響應式網頁設計)是透過瀏覽器的解析度來判斷要給使用者看到的樣貌

已經可以查詢出數據,並且緩存至Redis中。

獲取文章詳情

分析:文章詳情頁,文章的標題、作者、發布時間、所屬分類、標籤列表、文章內容(HTML和MarkDown)、鏈接、上下篇的標題和鏈接。

創建返回模型:PostDetailDto.cs

//PostDetailDto.cs
using System.Collections.Generic;

namespace Meowv.Blog.Application.Contracts.Blog
{
    public class PostDetailDto
    {
        /// <summary>
        /// 標題
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// 作者
        /// </summary>
        public string Author { get; set; }

        /// <summary>
        /// 鏈接
        /// </summary>
        public string Url { get; set; }

        /// <summary>
        /// HTML
        /// </summary>
        public string Html { get; set; }

        /// <summary>
        /// Markdown
        /// </summary>
        public string Markdown { get; set; }

        /// <summary>
        /// 創建時間
        /// </summary>
        public string CreationTime { get; set; }

        /// <summary>
        /// 分類
        /// </summary>
        public CategoryDto Category { get; set; }

        /// <summary>
        /// 標籤列表
        /// </summary>
        public IEnumerable<TagDto> Tags { get; set; }

        /// <summary>
        /// 上一篇
        /// </summary>
        public PostForPagedDto Previous { get; set; }

        /// <summary>
        /// 下一篇
        /// </summary>
        public PostForPagedDto Next { get; set; }
    }
}

同時添加CategoryDtoTagDtoPostForPagedDto

//CategoryDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{
    public class CategoryDto
    {
        /// <summary>
        /// 分類名稱
        /// </summary>
        public string CategoryName { get; set; }

        /// <summary>
        /// 展示名稱
        /// </summary>
        public string DisplayName { get; set; }
    }
}

//TagDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{
    public class TagDto
    {
        /// <summary>
        /// 標籤名稱
        /// </summary>
        public string TagName { get; set; }

        /// <summary>
        /// 展示名稱
        /// </summary>
        public string DisplayName { get; set; }
    }
}

//PostForPagedDto.cs
namespace Meowv.Blog.Application.Contracts.Blog
{
    public class PostForPagedDto
    {
        /// <summary>
        /// 標題
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// 鏈接
        /// </summary>
        public string Url { get; set; }
    }
}

添加獲取文章詳情接口和緩存的接口。

//IBlogService.Post.cs
public partial interface IBlogService
{
    /// <summary>
    /// 根據URL獲取文章詳情
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    Task<ServiceResult<PostDetailDto>> GetPostDetailAsync(string url);
}
//IBlogCacheService.Post.cs
public partial interface IBlogCacheService
{
    /// <summary>
    /// 根據URL獲取文章詳情
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    Task<ServiceResult<PostDetailDto>> GetPostDetailAsync(string url, Func<Task<ServiceResult<PostDetailDto>>> factory);
}

分別實現這兩個接口。

//BlogCacheService.Post.cs
public partial class BlogCacheService
{
    private const string KEY_GetPostDetail = "Blog:Post:GetPostDetail-{0}";

    /// <summary>
    /// 根據URL獲取文章詳情
    /// </summary>
    /// <param name="url"></param>
    /// <param name="factory"></param>
    /// <returns></returns>
    public async Task<ServiceResult<PostDetailDto>> GetPostDetailAsync(string url, Func<Task<ServiceResult<PostDetailDto>>> factory)
    {
        return await Cache.GetOrAddAsync(KEY_GetPostDetail.FormatWith(url), factory, CacheStrategy.ONE_DAY);
    }
}
//BlogService.Post.cs
/// <summary>
/// 根據URL獲取文章詳情
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public async Task<ServiceResult<PostDetailDto>> GetPostDetailAsync(string url)
{
    return await _blogCacheService.GetPostDetailAsync(url, async () =>
    {
        var result = new ServiceResult<PostDetailDto>();

        var post = await _postRepository.FindAsync(x => x.Url.Equals(url));

        if (null == post)
        {
            result.IsFailed(ResponseText.WHAT_NOT_EXIST.FormatWith("URL", url));
            return result;
        }

        var category = await _categoryRepository.GetAsync(post.CategoryId);

        var tags = from post_tags in await _postTagRepository.GetListAsync()
                   join tag in await _tagRepository.GetListAsync()
                   on post_tags.TagId equals tag.Id
                   where post_tags.PostId.Equals(post.Id)
                   select new TagDto
                   {
                       TagName = tag.TagName,
                       DisplayName = tag.DisplayName
                   };

        var previous = _postRepository.Where(x => x.CreationTime > post.CreationTime).Take(1).FirstOrDefault();
        var next = _postRepository.Where(x => x.CreationTime < post.CreationTime).OrderByDescending(x => x.CreationTime).Take(1).FirstOrDefault();

        var postDetail = new PostDetailDto
        {
            Title = post.Title,
            Author = post.Author,
            Url = post.Url,
            Html = post.Html,
            Markdown = post.Markdown,
            CreationTime = post.CreationTime.TryToDateTime(),
            Category = new CategoryDto
            {
                CategoryName = category.CategoryName,
                DisplayName = category.DisplayName
            },
            Tags = tags,
            Previous = previous == null ? null : new PostForPagedDto
            {
                Title = previous.Title,
                Url = previous.Url
            },
            Next = next == null ? null : new PostForPagedDto
            {
                Title = next.Title,
                Url = next.Url
            }
        };

        result.IsSuccess(postDetail);
        return result;
    });
}

ResponseText.WHAT_NOT_EXIST是定義在MeowvBlogConsts.cs的常量。

TryToDateTime()和列表查詢中的擴展方法一樣,轉換時間為想要的格式。

簡單說一下查詢邏輯,先根據參數url,查詢是否存在數據,如果文章不存在則返回錯誤消息。

然後根據 post.CategoryId 就可以查詢到當前文章的分類名稱。

聯合查詢post_tags和tag兩張表,指定查詢條件post.Id,查詢當前文章的所有標籤。

最後上下篇的邏輯也很簡單,上一篇取大於當前文章發布時間的第一篇,下一篇取時間倒序排序並且小於當前文章發布時間的第一篇文章。

最後將所有查詢到的數據賦值給輸出對象,返回,結束。

BlogController中添加API。

 /// <summary>
 /// 根據URL獲取文章詳情
 /// </summary>
 /// <param name="url"></param>
 /// <returns></returns>
 [HttpGet]
 [Route("post")]
 public async Task<ServiceResult<PostDetailDto>> GetPostDetailAsync(string url)
 {
     return await _blogService.GetPostDetailAsync(url);
 }

編譯運行,然後輸入URL查詢一條文章詳情數據。

成功輸出預期內容,緩存同時也是ok的。

開源地址:https://github.com/Meowv/Blog/tree/blog_tutorial

搭配下方課程學習更佳 ↓ ↓ ↓

http://gk.link/a/10iQ7

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

當全世界的人們隨著網路時代而改變向上時您還停留在『網站美醜不重要』的舊有思維嗎?機會是留給努力改變現況的人們,別再浪費一分一秒可以接觸商機的寶貴時間!

HTTP 冷知識 | HTTP 請求中,空格應該被編碼為 %20 還是 + ?_網頁設計

台北網頁設計公司這麼多該如何選擇?

網動是一群專業、熱情、向前行的工作團隊,我們擁有靈活的組織與溝通的能力,能傾聽客戶聲音,激發創意的火花,呈現完美的作品

HTTP 請求中,空格應該被編碼為什麼?今天我們走進 RFC 文檔W3C 文檔,了解一下這個「史詩級」大坑。

1.%20 還是 +

開始講解前先看個小測試,在瀏覽器里輸入 blank testblanktest 間有個空格),我們看看瀏覽器如何處理的:

從動圖可以看出瀏覽器把空格解析為一個加號「+」。

是不是感覺有些奇怪?我們再做個測試,用瀏覽器提供的幾個函數試一下:

encodeURIComponent("blank test"// "blank%20test"
encodeURI("q=blank test")        // "q=blank%20test"
new URLSearchParams("q=blank test").toString() // "q=blank+test"

image-20200524184735653

代碼是不會說謊的,其實上面的結果都是正確的,encode 結果不一樣,是因為 URI 規範和 W3C 規範衝突了,才會搞出這種讓人疑惑的烏龍事件。

2.衝突的協議

我們首先看看 URI 中的保留字,這些保留字不參与編碼。保留字符一共有兩大類:

  • gen-delims:
    :
    /
    ?
    #
    [
    ]
    @
  • sub-delims:
    !
    $
    &
    '
    (
    )
    *
    +
    ,
    ;
    =

URI 的編碼規則也很簡單,先把非限定範圍的字符轉為 16 進制,然後前面加百分號。

空格這種不安全字符轉為十六進制就是 0x20,前面再加上百分號 % 就是 %20

image-20200524184601512

所以這時候再看 encodeURIComponentencodeURI 的編碼結果,就是完全正確的。

既然空格轉為%20 是正確的,那轉為 + 是怎麼回事?這時候我們就要了解一下 HTML form 表單的歷史。

早期的網頁沒有 AJAX 的時候,提交數據都是通過 HTML 的 form 表單。form 表單的提交方法可以用 GET 也可以用 POST,大家可以在 MDN form 詞條上測試:

網頁設計最專業,超強功能平台可客製化

窩窩以「數位行銷」「品牌經營」「網站與應用程式」「印刷品設計」等四大主軸,為每一位客戶客製建立行銷脈絡及洞燭市場先機。

經過測試我們可以看出表單提交的內容中,空格都是轉為加號的,這種編碼類型就是 application/x-www-form-urlencoded,在 WHATWG 規範里是這樣定義的:

image-20200524185912590

到這裏基本上就破案了,URLSearchParams 做 encode 的時候,就按這個規範來的。我找到了 URLSearchParams 的 Polyfill 代碼,裏面就做了 %20+ 的映射:

replace = {
    '!''%21',
    "'"'%27',
    '(''%28',
    ')''%29',
    '~''%7E',
    '%20''+'// <= 就是這個
    '%00''\x00'
}

規範里對這個編碼類型還有解釋說明:

The application/x-www-form-urlencoded format is in many ways an aberrant monstrosity, the result of many years of implementation accidents and compromises leading to a set of requirements necessary for interoperability, but in no way representing good design practices. In particular, readers are cautioned to pay close attention to the twisted details involving repeated (and in some cases nested) conversions between character encodings and byte sequences. Unfortunately the format is in widespread use due to the prevalence of HTML forms.

這種編碼方式就不是個好的設計,不幸的是隨着 HTML form 表單的普及,這種格式已經推廣開了

其實上面一大段句話就是一個意思:這玩意兒設計的就是 ,但積重難返,大家還是忍一下吧

3.一句話總結

  • URI 規範里,空格 encode 為 %20application/x-www-form-urlencoded 格式里,空格 encode 為 +

  • 實際業務開發時,最好使用業內成熟的 HTTP 請求庫封裝請求,這些雜活兒累活兒框架都幹了;

  • 如果非要使用原生 AJAX 提交 application/x-www-form-urlencoded 格式的數據,不要手動拼接參數,要用 URLSearchParams 處理數據,這樣可以避免各種噁心的編碼衝突。

4.文章推薦

本文選自我的長文HTTP 規範中的那些暗坑,想要了解更多可點擊原文查看。

更多推薦:

  • webpack 中最易混淆的 5 個知識點,掘金快 800 贊了
  • webpack dll 是個什麼東西,看完就能
    擺脫繁瑣的 dll 配置
  • React Native 性能優化指南從渲染層的角度分析了 RN 性能優化的 6 個點,並以圖文形式講解了 FlatList 的實現原理
  • Web Scraper——輕量數據爬取利器 介紹了一個小巧的瀏覽器爬蟲插件,可以實現簡單的數據爬取功能

最後推薦一下我的個人公眾號:「滷蛋實驗室」,平時會分享一些前端技術和數據分析的內容,大家感興趣的話可以關注一波:


本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※推薦評價好的iphone維修中心

擁有專業的維修技術團隊,同時聘請資深iphone手機維修專家,現場說明手機問題,快速修理,沒修好不收錢

Redis詳解(十二)—— 緩存穿透、緩存擊穿、緩存雪崩_貨運

※評比南投搬家公司費用收費行情懶人包大公開

搬家價格與搬家費用透明合理,不亂收費。本公司提供下列三種搬家計費方案,由資深專業組長到府估價,替客戶量身規劃選擇最經濟節省的計費方式

  本篇博客我們來介紹Redis使用過程中需要注意的三種問題:緩存穿透、緩存擊穿、緩存雪崩。

1、緩存穿透

一、概念

  緩存穿透:緩存和數據庫中都沒有的數據,可用戶還是源源不斷的發起請求,導致每次請求都會到數據庫,從而壓垮數據庫。

  如下圖紅色的流程:

  

 

   比如客戶查詢一個根本不存在的東西,首先從Redis中查不到,然後會去數據庫中查詢,數據庫中也查詢不到,那麼就不會將數據放入到緩存中,後面如果還有類似源源不斷的請求,最後都會壓到數據庫來處理,從而給數據庫造成巨大的壓力。

二、解決辦法

  ①、業務層校驗

  用戶發過來的請求,根據請求參數進行校驗,對於明顯錯誤的參數,直接攔截返回。

  比如,請求參數為主鍵自增id,那麼對於請求小於0的id參數,明顯不符合,可以直接返回錯誤請求。

  ②、不存在數據設置短過期時間

  對於某個查詢為空的數據,可以將這個空結果進行Redis緩存,但是設置很短的過期時間,比如30s,可以根據實際業務設定。注意一定不要影響正常業務。

  ③、布隆過濾器

  關於布隆過濾器,後面會詳細介紹。布隆過濾器是一種數據結構,利用極小的內存,可以判斷大量的數據“一定不存在或者可能存在”。

  對於緩存擊穿,我們可以將查詢的數據條件都哈希到一個足夠大的布隆過濾器中,用戶發送的請求會先被布隆過濾器攔截,一定不存在的數據就直接攔截返回了,從而避免下一步對數據庫的壓力。

2、緩存擊穿

一、概念

  緩存擊穿:Redis中一個熱點key在失效的同時,大量的請求過來,從而會全部到達數據庫,壓垮數據庫。

  

   這裏要注意的是這是某一個熱點key過期失效,和後面介紹緩存雪崩是有區別的。比如淘寶雙十一,對於某個特價熱門的商品信息,緩存在Redis中,剛好0點,這個商品信息在Redis中過期查不到了,這時候大量的用戶又同時正好訪問這個商品,就會造成大量的請求同時到達數據庫。

二、解決辦法

  ①、設置熱點數據永不過期

※智慧手機時代的來臨,RWD網頁設計為架站首選

網動結合了許多網際網路業界的菁英共同研發簡單易操作的架站工具,及時性的更新,為客戶創造出更多的網路商機。

  對於某個需要頻繁獲取的信息,緩存在Redis中,並設置其永不過期。當然這種方式比較粗暴,對於某些業務場景是不適合的。

  ②、定時更新

  比如這個熱點數據的過期時間是1h,那麼每到59minutes時,通過定時任務去更新這個熱點key,並重新設置其過期時間。

  ③、互斥鎖

  這是解決緩存穿透比較常用的方法。

  互斥鎖簡單來說就是在Redis中根據key獲得的value值為空時,先鎖上,然後從數據庫加載,加載完畢,釋放鎖。若其他線程也在請求該key時,發現獲取鎖失敗,則睡眠一段時間(比如100ms)后重試。

3、緩存雪崩

一、概念

  緩存雪崩:Redis中緩存的數據大面積同時失效,或者Redis宕機,從而會導致大量請求直接到數據庫,壓垮數據庫。

  

   對於一個業務系統,如果Redis宕機或大面積的key同時過期,會導致大量請求同時打到數據庫,這是災難性的問題。

二、解決辦法

  ①、設置有效期均勻分佈

  避免緩存設置相近的有效期,我們可以在設置有效期時增加隨機值;

  或者統一規劃有效期,使得過期時間均勻分佈。

  ②、數據預熱

  對於即將來臨的大量請求,我們可以提前走一遍系統,將數據提前緩存在Redis中,並設置不同的過期時間。

  ③、保證Redis服務高可用

  前面我們介紹過Redis的哨兵模式和集群模式,為防止Redis集群單節點故障,可以通過這兩種模式實現高可用。

  

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※回頭車貨運收費標準

宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念

Golang基礎教程——map使用篇_包裝設計

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網動廣告出品的網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上她。

本文始發於個人公眾號:TechFlow,原創不易,求個關注

今天是golang專題的第7篇文章,我們來聊聊golang當中map的用法。

map這個數據結構我們經常使用,存儲的是key-value的鍵值對。在C++/java當中叫做map,在Python中叫做dict。這些數據結構的名稱雖然不經相同,背後的技術支撐也不一定一樣,比如說C++的map是紅黑樹實現的,Java中的hashmap則是通過hash表。但是使用起來的方法都差不多,除了Java是通過get方法獲取鍵值之外,C++、Python和golang都是通過方括號獲取的。

聲明與初始化

golang中的map聲明非常簡單,我們用map關鍵字表示聲明一個map,然後在方括號內填上key的類型,方括號外填上value的類型。

var m map[string] int

這樣我們就聲明好了一個map。

但是要注意,這樣聲明得到的是一個空的map,map的零值是nil,可以理解成空指針。所以我們不能直接去操作這個m,否則會得到一個panic。

panic: assignment to entry in nil map

panic在golang當中表示非常嚴重不可恢復的錯誤,可以恢復的錯誤有些類似於Java或者是其他語言當中的異常,當異常出現的時候,我們可以選擇handle住它們,讓程序不崩潰繼續運行。而那些非常嚴重,無法handle的異常在golang當中稱為panic。

golang當中的異常處理機制和其他語言相差很大,整體的邏輯和內核都不太一樣。當然這個是一個比較大的話題,我們這裏可以簡單將它理解成error就行了。

回到map上來,我們聲明了一個map之後,想要使用它還需要對它進行初始化。使用它的方法也很簡單,就是使用make方法創建出一個實例來。它的用法和之前通過make創建元組非常類似:

m = make(map[string] int)

// 我們還可以指定創建出來的map的存儲能力的大小
m = make(map[string] int, 100)

我們也可以在聲明的時候把初始化也寫上:

var m = map[string] int {"abc": 3, "ccd": 4}

當然也可以通過賦值運算符,直接make出一個空的map來:

m := make(map[string] int)

增刪改查

map創建好了當然是要用的,整體使用起來和Python當中的dict比較像,比較簡單直觀,沒有太多彎彎繞的東西。我們一個一個來看,首先是map的添加元素。map的添加元素直接用方括號賦值即可:

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

上新台中搬家公司提供您一套專業有效率且人性化的辦公室搬遷、公司行號搬家及工廠遷廠的搬家服務

m["abc"] = 4

同樣,我們需要保證這裏的m經過初始化,否則也會包nil的panic。如果key值在map當中已經存在,那麼會自動替換掉原本的key。也就是說map的更新和添加元素都是一樣的,都是通過這種方式。如果不存在就是添加,否則則是更新。

刪除元素也很簡單,和Python當中類似,通過delete關鍵字刪除

delete(m, "abc")

當我們刪除key的時候,如果是其他的語言,我們需要判斷這個key值是否存在,否則的話不能刪除,或者是會引起異常。在golang當中並不會,對這點做了優化。如果要刪除的key值原本就不在map當中,那麼當我們調用了delete之後,什麼也不會發生。但是有一點,必須要保證傳入的map不為nil,否則也會引起panic。

最後,我們看下元素的查找。對於Java和Python來說我們都是通過一些判斷語句來進行判斷的,比如java的話是containsKey,Python的話用in操作符。在golang當中我們則是直接通過方括號進行查詢,那麼這就有了一個問題,如果key不在其中怎麼辦?

如果是其他語言,我們直接訪問一個不存在的key是會拋出異常的,但是在golang當中不會觸發panic,因為它會額外返回一個bool類型的元素表示元素是否查找到。所以我們可以同時用兩個變量去接收,如果第二個變量為True的話,就說明查找成功了。

進一步,我們還可以將這個邏輯和if的初始化操作合在一起:

if val, ok := m["1234"]; ok {
    fmt.Println(val)
}

這裏的ok就表示查找是否成功,這也是golang當中map查找的慣用寫法。

最後, 我們看一個實際運用map的例子,通過map來生成統計字符串當中單詞數量的wordCount:

package main

import (
 "golang.org/x/tour/wc"
 "strings"
)

func WordCount(s string) map[string]int {
 cnt := make(map[string]int)
    // 通過Split方法拆分字符串
 for _, str:= range strings.Split(s){
        // 直接++即可,golang會自動填充
  cnt[str]++
 }
 return cnt
}

func main() {
 wc.Test(WordCount)
}

總結

到這裏,關於golang當中map的使用就算是介紹完了。我們可以發現,map一如既往地體現了golang語法精簡的特點。比如通過返回error的操作省略了判斷元素是否存在map當中的操作,剛開始的時候會覺得有些不太適應,但是接觸多了之後,會發現這些都是有套路的。golang的套路就是精簡,能省就省,能簡單絕不複雜。

這一點不僅在map上體現,在其他特性上也是一樣。在後續的內容當中,我們還會繼續感知這一點。

如果喜歡本文,可以的話,請點個關注,給我一點鼓勵,也方便獲取更多文章。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※產品缺大量曝光嗎?你需要的是一流包裝設計!

窩窩觸角包含自媒體、自有平台及其他國家營銷業務等,多角化經營並具有國際觀的永續理念。

小米的“鐵蹄”_網頁設計公司

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。

雷軍說,小米的模式是「互聯網+製造」。

這顯然指的是現在的小米,一個不同於2010年成立之初,為了一塊手機屏幕、一家代工廠商忙得焦頭爛額的小米。

在過往十年裡,小米恰如其時地趕上了智能手機的全生命周期,從開局到全盛、再到如今的幾近飽和,智能手機成就了移動互聯網,也成就了小米。

小米卻不僅僅是一家手機廠商,至少在這位當時已將金山軟件送上港交所、在投行浸潤多年的知名投資人眼裡,小米應該有更大的格局。

“其實很多人不懂小米,”在接受《中國企業家》採訪時,雷軍如是說。

過往幾年,雷軍多次強調“小米從來都不是一家只做硬件的公司”。實際上,小米在成立之初甚至差點兒成了下一個騰訊。

即使在最終選定智能手機賽道后,小米也一再出圈,做生態鏈、做家電、做物聯網、做“地產”……

「互聯網+製造」,也只不過是小米又一次打破常規的瘋狂生長。

差點兒成了下一個騰訊

小米之所以是小米,是因為智能手機。

其實,在小米成立之初,也曾抓到過另一個機遇,IM(即時通訊)。

2010年10月19日,加拿大滑鐵盧大學一個學生團隊研發出了一款軟件,名為Kik Message。

這是一款基於本地通訊錄與聯繫人直接建立聯繫,並在此基礎上實現免費短信聊天的即時通訊工具,發布兩周內,註冊用戶數就超過了100萬。

當時,本來打算做智能手機、對移動互聯網行業高度關注的小米團隊,最先關注到了這款軟件,僅在一個月後(2010年12月10日),第一代米聊誕生。

米聊誕生時,小米還沒有手機,不過這不要緊,因為當時的米聊是直接上線到安卓、iOS兩大應用市場中的,對於當時擁有多位來自谷歌的大神的小米初創團隊來說,干這樣一款手機軟件自然是輕車熟路。

不過,當時小米團隊中鮮有人能夠預見,這將是一門體量不亞於小米規劃中的主業——智能手機的生意。

自米聊發布后,用戶數幾乎每周翻一倍,短短几個月的時間里,用戶數就達到了100萬,這讓雷軍看到了米聊成為下一代即時通訊工具的希望。

不過,雷軍當時有一個擔心,騰訊會不會跟進。

雷軍當年有三種設想,小米官方授權傳記《一往無前》中對此有詳細描述:

如果騰訊用QQ這個產品來迎戰米聊的話,小米尚有一絲機會,因為QQ在手機上的體驗過重,不符合移動互聯網短平快的用戶體驗;

如果騰訊沒有犯任何戰略錯誤,選擇用完全相同的產品形態來迎戰米聊的話,只有在它能給米聊一年搶跑時間的前提下,小米才有50%的勝算;

如果騰訊在一年之內拿出一模一樣的產品,那麼,騰訊的綜合資源是小米的一萬倍,小米將處於完全的弱勢,屆時,騰訊會把全部的工程資源和推廣資源撲上來,小米獲勝的概率將是零。

結果是,騰訊在這一步上沒有犯錯,而且跟進得相當及時,甚至在關鍵時刻集結重兵壓線。

為什麼當時這家已經成立13年的上市公司會這麼在乎這款“小產品”呢?

原因在於,即時通訊是騰訊的“基本盤”,騰訊丟不起。

就在小米開始籌備米聊過程中,偏安一隅的張小龍帶着一個不到10人的小團隊開始在內部研發同樣的產品。經過兩個月的內部研發后,2011年1月21日,微信正式上線。

接下來就是一場用戶搶奪的近身肉搏戰。

在隨後一段時間里,用戶增長為服務器帶來的壓力讓兩家公司壓力山大,紛紛調來核心團隊開始大軍團作戰,最後的戰局如當下所見——QQ、微信成為騰訊生態體系的兩大“基本盤”,用米聊贏得不少關注度的小米最終轉向做智能手機這一“正業”上

試想一下,如果當時騰訊晚些時日入場、或者小米有足夠的彈藥,小米或將不再是現在的小米,很可能已經成了下一個騰訊。

這是小米離成為“互聯網大佬”最近的一次,或許雷軍不會想到,在此之後的幾年裡,他需要無數次向人們解釋:「小米是一家互聯網公司,不是一家只做硬件的公司」。

小米的“鐵人三項”

做即時通訊無果的小米,最終回到了智能手機這條最初規劃的主業上。

作為互聯網圈內知名投資人、目標全球市場的雷軍,對智能手機的商業模式有自己獨特的理解。

他將智能手機商業模式總結為“鐵人三項”——硬件+軟件+互聯網。

用雷軍的話解釋就是,“把軟件、硬件和互聯網融為一體,可以另闢蹊徑、‘降維攻擊’”。

現在回過頭來看,雷軍提出的“鐵人三項”和喬布斯做智能手機的“封閉體系完美論”如出一轍。

不過也正是用這樣的商業模式,雷軍“勸服”了一個初創團隊,最終將小米手機帶進了全球前五。甚至在今年Q3,小米手機全球出貨量首超蘋果,全球市場排名位列第三。

同樣是在做智能手機這幾年裡,在手機廠商同行眼裡,有點另類的小米還做對了另一件事——小米生態鏈。

生態鏈構建的小米疆界

2013年年底,雷軍做出一個決定——用投資的方式孵化智能硬件公司。

雷軍在小米成立之初提出的“鐵人三項”模式不僅適用於智能手機,同樣適用於大部分智能硬件。

這就是有了後來眾人皆知的小米生態鏈。

談到小米生態鏈,就不得不提及另一位小米聯合創始人,劉德。

劉德是工業設計科班出身,開過設計公司、當過大學老師、到過美國頂尖設計名校留學深造。進入小米后,主抓的是小米手機的工業設計,與雷軍不同,在受命搭建小米生態鏈之前,劉德還不曾干過投資這件事。

正式接手搭建小米生態鏈工作后,劉德從內部組建起一支小型投資團隊,和劉德一樣,這個投資團隊成員是由工程師和設計師組成,對於投資這件事兒,都是只聽過、沒幹過。

正是這支毫無經驗的投資團隊,在短短几年時間里,用工程師思維投出了一個小米生態鏈,小米生態鏈也不負眾望地在互聯網世界里,為小米劃出了自己的疆界。

回到最初小米的設想,雷軍最初為這支投資團隊“划的重點”是「手機周邊」。

早年間小米投資或孵化出的做移動電源的紫米、做數據線的碩米、做智能手環的華米、做藍牙耳機的萬魔聲學,都是沿着這一思路。

在開啟生態鏈計劃時,雷軍曾為小米定下“5年內投資100家生態鏈企業”的目標。

100家生態鏈企業自然不會全都是「手機周邊」,「手機周邊」之外,小米生態鏈還有另外兩個圈層——「智能硬件」、「生活耗材」。

與小米生態鏈計劃幾乎同時展開的,還有小米的IoT業務,小米的IoT業務最初源於一個Wi-Fi模組。

2014年年初的一天,小米聯合創始人黃江吉帶着高自光、殷明君,拿着一個Wi-Fi模組找到雷軍說,“我們研發出了一個Wi-Fi小模組,只要把這個小模組放到任何一個硬件里,這個硬件立刻可以被手機控制,從而連接到我們的IoT網絡中。”

現場,他們還通過手機、燈泡為雷軍進行了Demo演示。

在這之後,殷明君的創業團隊被小米收購,小米IoT部門初步形成。

小米當時的IoT業務開展的並不順利,在外部與家電廠商尋求合作屢屢碰壁后,他們最終將Wi-Fi模組首先應用到了小米生態鏈企業智米的空氣凈化器上。

某種意義上來看,小米的IoT和生態鏈天然互補,生態鏈為IoT提供了落地空間,IoT為生態鏈提供了更高的價值和意義。這也成就了後來小米相對封閉的生態。

隨後幾年時間里,小米生態鏈通過“效率”、“成本”兩把尖刀,硬生生在互聯網世界中劃出了一道印記,這道印記被稱為“小米模式”。

在小米生態鏈出現之前,BAT是擺在所有互聯網創業者面前的三座大山,吳曉波在《騰訊傳》中曾這樣寫道:

在風險甚至流傳着這樣的一個說法:

當一位創業者向投資人解說自己的項目的時候,必須要回答一個問題——騰訊會不會做這個項目?或者,如果騰訊進入,你如何保證不被“幹掉”?

雷軍也曾表示,“在我們布局IoT的同時,也是為了繞開BAT三座大山。”

IoT+生態鏈,讓小米繞開了“三座大山”,開闢了一個新戰場。尤其隨着智能家居、產業互聯網等概念在國內興起,在其他互聯網創業者眼中,小米開始成了一座想要“繞開”的山。

近日在科創板上市的平衡車領域的頭部企業九號機器人,也是小米生態鏈早期投資的智能硬件企業之一。早年間,九號機器人創始人高祿峰此前在接受媒體採訪時曾透露:

當時正在思考生態鏈布局的小米已經將我們的競爭對手都看過了,換句話說,如果小米不投我們,投了別人,我們會非常被動,於是我們開始主動接觸小米。

最終小米投資了九號機器人,2015年10月19日,兩家合作的第一款產品「九號平衡車」,售價1999元,再次打破了行業定價規律。

對於將硬件凈利潤不超過5%的寫進招股書的小米,眾口不一。有人認為,小米這是用低價扼殺了國內同行的生存空間、創新空間;也有人認為,這是又一家有野心的中國企業的崛起。

倒是在翻看《小米生態鏈戰地筆記》一書時,雷鋒網在雷軍為這本書寫注寫的序中看到這樣一句話:

小米,就是要做中國製造業的鯰魚。

隨後幾年裡,小米陸續投資或孵化了近300家企業,在互聯網世界里構建起了小米的疆界,小米這條“鯰魚”也悄無聲息地游進了家電領域。

王川和大家電

與其他手機廠商同行不同,小米一直都是一家不安分的手機廠商。

在建立小米生態鏈之前,小米已經親自下場做了路由器、智能電視。其中,小米電視的靈魂人物是小米第八位聯合創始人,王川。

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。

說起來,王川其實不在小米初創團隊之列,也沒有和雷軍一起喝過那碗小米粥,不過,王川卻是又一位在加入小米之前就已經實現了財富自由的人。

王川同樣是一位“帶資進組”的硬件專家。

2012年,加入小米之前,王川就看到了智能電視這一市場機遇。當時,蘋果、谷歌都已經推出了電視盒子,王川的多看科技也開始着手面向國內市場研發這一款產品。這一產品最終在當年11月面世,被命名為小米盒子,成為王川帶給小米的第一份“禮物”。

小米的智能電視要比小米盒子晚一年,那時的智能電視更多是被稱為互聯網電視。

與眾多互聯網風口一樣,2013年,互聯網電視風口同樣引來了不少虎狼之師。

9月5日,在小米2013年年度發布會上,小米電視正式亮相,售價2999元。

然而,即便在國內,想要做互聯網電視的也不只小米一家。國內主流電視廠商聯合互聯網廠商同期發布的互聯網電視並不少見。

9月3日,愛奇藝、TCL聯合發布“TV+”,經典版TV+定價2999元;

9月10日,阿里、創維聯合發布第一款互聯網電視——搭載阿里TV操作系統及創維天賜系統的創維酷開55K1和42K1;

……

此外,當時還有個風頭無兩的樂視。

樂視在5月發布的超級電視S40直接將售價直接壓到1999元,X60在9月23日宣布與騰訊達成深度合作,由騰訊旗下綜合性電商平台易迅網通過“集采、包銷”方式銷售樂視TV·超級電視X60。

當年,幼年的小米電視並不是一枝獨秀,甚至算不上出彩,也正是這個看似不突出的“幼崽”,自那個風雨飄搖的年代堅持到了現在,並成為今日決定小米江湖地位的一款關鍵產品。

在剛剛過去的2019年,小米電視出貨量破千萬台,樂視卻再也不是那個曾經的樂視。

正是由於在小米電視上的大獲全勝,當小米在2019年大刀闊斧地進入大家電領域時,王川再次披甲上陣。

2019年5月17日,小米進行組織架構調整,宣布成立大家電事業部,任命王川為大家電事業部總裁,負責除電視之外的空調、冰箱、洗衣機等大家電品類的業務開展和團隊管理工作。

在小米官宣進入大家電領域之前,已經早早通過生態鏈摸進了大家電領域:

2017年3月11日,小米生態鏈企業雲米發布了雲米互聯網智能冰箱,隨後,雲米又發布了互聯網洗衣機;

2017年8月10日,做空氣凈化器起家的智米發布了1.5P全直流變頻空調;

……

在2019年4月的小米電視發布會上,雷軍再次提及,“大家電業務是小米AIoT戰略重要組成部分和未來10年持續發展藍圖的核心拼圖之一。”

對於小米做家電,雷鋒網接觸的不少行業人士都表示,對於要做智能家居產業鏈的小米而言,做家電也在意料之中。

互聯網廠商做大家電、做白電會有什麼門檻嗎?

雷鋒網向家電行業資深專家了解到:

智能家電其實是家電行業和互聯網行業的一個交集,這個領域就技術難度、市場推廣等方面來說,互聯網企業比傳統白電企業更有優勢。

在具體的生產製造方面,互聯網企業完全可以找OEM代工解決;從產品設計方面來看,他們與有着二三十年行業沉澱的家電行業頭部企業還是有一定差距,現在主要蠶食的其實是中小型家電企業的市場份額。

小米的大家電事業部成立后,不到一年時間里,通過「小米」、「米家」兩個品牌布局了“空冰洗、廚衛電”在內的幾乎所有家電產品,甚至在年底還發布了小米互聯網空調,着實還是為董小姐捏了一把汗。

2013年,在央視年度經濟人物頒獎典禮上,雷軍與董明珠定下“10億賭約”時,曾有一次戲劇性的對話:

董明珠:如果全世界的工廠都關掉了,你還有銷售(額)嗎?

雷軍:我覺得董總是在挑撥離間,小米用的是最好的工廠和最好的供應鏈……

董明珠:(如果)我(的工廠)不給你做呢?

雷軍:今天強調的是專業化分工,做工廠的把工廠做好,做產品的專心做產品……

董明珠:那我空調給你賣算了。

雷軍:可以考慮呀~

董小姐有所不知的是,雷軍當時說的可以考慮的不僅僅是“小米賣空調”,還有“小米開工廠”。

從“敬畏製造業”到“+製造”

在事後回憶起這次很大程度上節目組安排的“對賭”時,雷軍坦言:(當時)確實有點膨脹了。

“膨脹”是因為小米創立前三年吃到了功能機轉智能機的紅利,一直處於“瘋長模式”,手機銷量和公司估值像是吹氣球一樣在快速飆升。到2014年,小米手機已經以12.5%的市佔率位居國內第一(全球第三)。

2014年年底,小米完成又一輪11億美元融資后,估值高達450億美元,5年翻了180倍。

承認“膨脹了”是因為在三年瘋長后,小米開始遭遇增長瓶頸,增速放緩,甚至開始受到質疑。

美國《華爾街日報》援引知情人士消息稱,小米2015年未能達到8000萬部智能手機的銷售預期,投資者也開始質疑該公司高達450億美元的估值。

在隨後接受媒體採訪時,雷軍也透露,小米從2016年提出“要敬畏製造業”,並開始大規模補課硬件、下決心植根製造業。

經過三年補課,小米智能工廠最終出現在雷軍今年的十周年公開演講中。

雷軍說,為了做這間工廠,小米在過去三年時間里投資了110家做智能裝備的公司。

在年底的MIDC 2020上,小米智能工廠的部分細節逐漸對外公布:

除了貼片機,其它絕大部分生產設備採用的都是小米自研的設備。

一期工廠中除了上下料外,實現了全部智能化,一期自動化率達到63%,年底對整機組裝和包裝環節優化后,自動化率提升至75%。

同樣是在年底大會上,小米智能工廠的三年規劃和整體規劃圖也被和盤托出:

2019年,進行自動化建設,通過機器人與自動化建設替代人工;

2020年,進行網絡化建設,通過全面網絡化進行數據採集和應用;

2021年,進行智能化建設,實現基於數據和知識的智能決策。

從做手機跨到做智能工廠,跨度究竟有多大?

雷鋒網向智能製造相關從業人士了解到:

自動化只是智能工廠的初級階段,目前自動化產線相關技術也已經比較成熟,只要找到合適的人,有足夠的經費投入,已經算不上什麼門檻。

推進智能工廠,並不能降低小米手機的成本。手機是一個迭代非常快的產業,生產手機外殼或相關零配件的專用機床,往往三個月到半年就要更新換代,這方面生產設備的成本非常高。即便是智能工廠,成本也不低,所以小米的智能工廠,目前更多應該是應用在市場周期更長的高端手機,例如小米10至尊版。

小米智能工廠的想象空間是基於小米對於用戶需求的收集反饋,打通消費者需求、研發和製造的閉環,類似阿里的犀牛智造。

雷軍是在不惑之年創立的小米,他曾說,改變製造業是小米的終極夢想。

現在,10歲的小米正在用互聯網改變製造業,也在用製造業改變小米。

小米的“鐵蹄”,沒有邊界

如果在小米公司內部孵化硬件企業,必然會降低公司的專註度,這對公司的發展是致命的。

小米成長初期,雷軍曾這樣考慮。

因此也就有了“不做航母,做艦隊”一說,有了小米生態鏈。

不過,在小米成立十年之際再回頭看,你會發現,通過投資、孵化,在手機之外,小米前沖后撞,給自己開闢出一個廣闊的疆域。

我們可以看到,小米除去有手機、音箱等智能硬件外,同時:

在家電行業,就“功能機”轉“智能機”之際,抓住機會,跨界爭奪紅利期;

在製造行業,憑藉自身供應鏈優勢、互聯網基因,借政策東風,加碼加力;

甚至在地產行業,在智能家居、智慧社區中,也可見「小米+生態鏈+金山雲」組合的身影。

小米曾經官宣,在物聯網周期內,小米有「1+4+X」的戰略布局。

而其實,真正的小米,似乎沒有邊界。

就像曾經的一代天驕成吉思汗,“鐵蹄”所到之處,即為帝國疆域。

【本文作者王金旺,由合作夥伴微信公眾號:雷鋒網授權發布,文章版權歸原作者及原出處所有,轉載請聯繫原出處。文章系作者個人觀點,不代表立場。如內容、圖片有任何版權問題,請聯繫(editor@zero2ipo.com.cn)處理。】

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境

自如要求業主合同期降租,否則強制解約,租客也被下“逐客令”_網頁設計公司

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

當全世界的人們隨著網路時代而改變向上時您還停留在『網站美醜不重要』的舊有思維嗎?機會是留給努力改變現況的人們,別再浪費一分一秒可以接觸商機的寶貴時間!

近日蛋殼事件持續發酵,不少租客被驅逐、無處可去,房東收不回房租、左右為難,租金貸的弊端盡顯,長租公寓行業存在的問題被充分暴露。

而作為長租公寓行業頭部玩家的自如,被很多打工人看成租房的重要選擇。

但是自如真的靠譜嗎?就在最近,不斷有業主反映自如要求業主合同期內降租,不同意就強制解約,還要賠償違約金。租客也被下逐客令,並且不按合同賠償。

總結一下,自如先是以疫情影響等原因要求業主合同期內降租,否則就單方面解約,而且還算業主違約,須支付違約金,比如裝修費用等。租客則不得不搬離,也不能獲得合同規定的賠償。

有業主更是直言“要麼降租,要麼陪他們裝修費用,呵呵,我們就是任人宰割的小羊,賺了錢是他們的,賠了錢是我們的”。

三言財經了解到,有業主表示從今年6月份自如就打電話談降租,理由是疫情影響,至今中間談了幾次降租的事,但是業主始終沒有同意。

就在最近該業主突然在APP上發現雙方合同正處於解約中。自如在合同期內強行降租,不同意就強制解約。此外,該業主稱,自如強行解約還會算成業主違約,業主還要賠償裝修費。

對於下一步的維權,該業主表示如果12月的房租超過15天沒有支付,會起訴自如。他還稱,自己所在的維權群里已近500人,群里有大量起訴自如的業主。

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

透過資料庫的網站架設建置,建立公司的形象或購物系統,並提供最人性化的使用介面,讓使用者能即時接收到相關的資訊

事實上在微博上,#自如要求業主合同期內降租#的話題已經有近千萬的閱讀量,而相關的爆料最早從今年6月份就已經出現。

隨着最近蛋殼事件的引爆,自如的業主和租客也感受到了緊張,相關爆料也開始多起來。

自如的做法,實際將業主和租客也放到了對立面,三方的矛盾變得無法調和。

對於業主和租客,都面臨兩方的壓力。自如這招算是轉嫁了降低成本所引發的矛盾爆發點。

不僅對業主,自如是兩頭解約,還將問題轉嫁到業主身上。

有租客表示,在強制業主解約后,自如對合約期內的租客下達逐客令。

該租客表示,從業主口中得知,自如拖欠業主兩個月房租,導致業主不得不解約,收回房屋,並沒有收到違約金。但自如卻表述是業主主動解約,還稱業主拒付違約金。

有業主提供的維權群里,維權人員自發的製作了降租解約的應對策略。其中細節及其詳盡,這隻能說維權並不是一件容易的事。

最後對於維權,筆者還是建議受害者們要及時保存證據,在法律範圍內合法維權,多嘗試各種途徑。

【本文作者三言財經,由合作夥伴三言財經授權發布,文章版權歸原作者及原出處所有,轉載請聯繫原出處。文章系作者個人觀點,不代表立場。如內容、圖片有任何版權問題,請聯繫(editor@zero2ipo.com.cn)處理。】

※想知道最厲害的網頁設計公司嚨底家"!

RWD(響應式網頁設計)是透過瀏覽器的解析度來判斷要給使用者看到的樣貌

成功當如李誠儒,失敗要學馬保國_網頁設計

※推薦評價好的iphone維修中心

擁有專業的維修技術團隊,同時聘請資深iphone手機維修專家,現場說明手機問題,快速修理,沒修好不收錢

66歲的李誠儒有了個站,69歲的馬保國“耗子尾汁”的商標被搶注。也許,我們很難把李誠儒和馬保國放在同一層面討論,但分析兩人的“翻紅”路徑卻不難發現冥冥中的聯繫:

一個是演藝圈的評論大咖,一個是武林界的功夫專家。一個說“如鯁在喉”,一個說“耗子尾汁”。一個在《演員請就位》炮轟娛樂怪現狀,一個在B站血洗成為新晉鬼畜王。

若說沒奇緣,怎生兩個他?李誠儒是一個精英主義的批評者,他有着成功之後的淡泊逍遙,以至於說什麼大家都很信;馬保國是一個大眾語境的被嘲笑者,儘管永遠翻車但永遠叫囂武德,這導致他說什麼大家都不信。

李誠儒只要講自己的故事就足以表達,而馬保國卻不停地用編故事來將自己美化。無論是讓人“都很信”的李誠儒,還是讓人“都不信”的馬保國,他們的符號價值都有一半是受眾賦予的。

大眾需要用高屋建瓴的姿態,去沖刷演技拉垮的娛樂景觀。同時,也需要用蚍蜉撼樹的視角,來解構庸碌瑣碎的日常生活。

一邊仰望星空崇敬理想,一邊腳踏實地嘲諷鬧劇。李誠儒和馬保國是兩種情緒,更是兩種容器,或許還是老頭網紅壁壘分明的兩條路徑。

布加齊列夫曾指出,符號化發生於一物“獲得了超出它作為自在與自為之物的個別存在的意義時”。如同一恭弘=叶 恭弘知秋的“一恭弘=叶 恭弘”,窺斑知豹的“一斑”,李誠儒和馬保國的延展意義,是被網友的目光打量出來的。

我在英國教功夫

我在北京演《大腕》

《下個,路口,見》里唱“當半個地球外還有個你,當相遇還沒到對的時機”,很適合2001年的馬保國和李誠儒。

這一年,已經通過做生意完成階層躍遷的李誠儒,在《大腕》里奉獻了令人拍案叫絕的演出。

房地產怎麼搞?黃金地段請法國設計師,電梯直接入戶,戶型最小四百平起步。孩子教育怎麼抓?社區裏面建一個貴族學校,教材直接用哈佛的。

順義媽媽們20年後才意識到的問題,李誠儒當時已經用“精神病”的方式點出。“不求最好,但求最貴!”長達1分26秒的長鏡頭,除了精湛的演技更離不開他本人的商海經歷。

這位“大款”既有當初創建西單“特別特商場”日進斗金的輝煌,也有炒匯時一着不慎的慘敗。在東單擺地攤,李誠儒琢磨歐版風衣多而日式風衣少。改變進貨思路后,讓10萬件風衣銷售一空。開“特別特”又把售貨員包裝成青春靚麗的導購小姐,短短15天名噪京城,一天的純利就50萬。

當時區政府要求各個經商單位必須晚上出攤,讓東單亮起來。有一天李誠儒親自壓陣,正好遇見了1980年北電第一屆業餘演員進修班的同學趙寶剛。

此時剛拍完《渴望》的趙寶剛問李誠儒想不想演《編輯部的故事》,一拍即合,就有了劇中李誠儒飾演的“騙子”。

12年的經商生涯,成了李誠儒重要的藝術源泉。而身無長處的馬保國,在2001年陪兒子到英國留學后,做起了開館收徒補貼學費的副業。

在《我在英國教功夫》一書里,馬保國試圖將自己包裝成一位學武不輟的勤奮武者。

“在南陽師專的三年裡,我每天堅持練功三個多小時”、“到畢業之前,我一拳就能把泡桐樹樹皮打飛,外家功夫有了很大長進”。馬保國很看重類似的生活細節,但這本書更像是簡約版的文人武俠小說,而不是職業習武者的生活記錄。

由於沒有受過系統的武學訓練,馬保國的武功水準只能達到底層化、業餘化甚至玩笑化的水準。他在書中記錄的師父郭雲深,把人打得飛出幾米高,無視牛頓只剩牛逼。類似的傳奇描述,無一例外地都發生在未有視頻記錄的私密空間。

作為編劇,馬保國最精彩的故事是2001年他去總公司機關大院開會,馬保國意外喝退了八九名手持短棍的民工。當時一位中年民警問馬保國:“老同志,我看你有真功夫,為啥不還手?”馬保國回答:“敢還手嗎?打傷人誰負責?”警察深以為然,連說:“對,對!”

李誠儒有經歷,演戲不費勁。馬保國沒經歷,編劇下功夫。這一年的英倫與中國,兩个中年人都開始了二度創業。李誠儒由商界進入演藝圈,馬保國則從下崗潮流入江湖。

以商養文VS以德保身

網頁設計最專業,超強功能平台可客製化

窩窩以「數位行銷」「品牌經營」「網站與應用程式」「印刷品設計」等四大主軸,為每一位客戶客製建立行銷脈絡及洞燭市場先機。

《編輯部的故事》是李誠儒的第一部戲,隨後《過把癮》中的錢康,《東邊日出西邊雨》中的吳永民,《清明上河圖》中的陳德張都是李誠儒的代表作。雖說角色不多,但他獨特的冷峻幽默令人過目不忘。

但在《無雪的冬天》后,已經42歲的李誠儒面臨着無戲可拍的尷尬。有一樣東西像缺鈣一樣,阻礙他的繼續發展,這個東西就是錢。意識到娛樂圈“有奶就是娘”的規矩,李誠儒開始自己做製片人。

他為自己量身打造了《重案六組》的刑警大曾,火到什麼程度呢?不管李誠儒走到哪兒,都有人喊他大曾。該劇投資500萬,最後賣了1500萬。

嘗到甜頭的李誠儒趁熱打鐵,買斷了老舍《我這一輩子》的改編權。不但把戲最多的劉方子留給自己,還在版權轉讓協議里寫明“劉方子這個角色必須由李誠儒出演”。

現在流行狙明星“帶資進組”,而李誠儒則是更霸道的“以商養文”。2005年,李誠儒在北京開了“海雨天風”火鍋城。他的賬是這麼算的:火鍋城若盈利得好,一年能有450萬的利潤,這些錢拿來拍一部由他主演的20集電視劇不香嗎?

海歸后的馬保國,則比其他武者更通曉現代媒介社會的生存法則。那就是,不顧一切地佔領輿論高地,對武術史上的“古典完人”進行再度扮演。為了打造一種全知全能的武師形象,他先從自己的武學傳承吹起。

在馬保國督導眾多弟子練功的視頻里,他驕傲地說:“馬家功夫沒有套路,我父親參加抗日戰爭,和日本鬼子進行過白刃戰,殺他們易如反掌。”接着,他通過故事的不斷疊加來證明自己武藝超凡。對決河南省75KG的冠軍錢洪亮,他聲稱“右鞭腿打我腿上了,他自己飛出去了。”

類似的說教均無任何證據,顯然是一種孤證式的闡釋和自我吹噓。馬保國的劇本情節非常老舊,基本復刻七八十年代的邵氏彩色武打片。《我在英國教功夫》里甚至有英國人去砸場子的描寫,《恭弘=叶 恭弘問》電影不找馬老當顧問也是可惜。

馬保國還試圖模仿夜讀《春秋》的關羽,他的宣傳視頻偶爾會崩出“punch”、“follow me”、“show me”之類的英文單詞和短句。加上他身着中式對襟裝,在中式條桌上放置筆墨,抑揚頓挫地講解渾元理念,頗得武術表演之妙。

如果說李誠儒的模式是“以商養文”的話,那麼馬保國就是典型的“以德保身”。當所有專業人士批評馬保國的不專業時,他完全可以用一種羽扇綸巾的“文士形象”舌戰群儒,從而擺脫輿論危機。

為了演戲,不愛做生意的李誠儒要努力掙票子。為了票子,不會武術的馬保國要努力演戲。看似完美的斜杠青年變成“斜杠中年”后,只剩下了“為了XX而XX”的狼狽。

網紅的語境挖掘與互動賦能

在重新走到大眾視野之前,李誠儒和馬保國都“涼了”一段時間。

李誠儒“以商養文”的模式失靈,2018年自導自演的《大導歸來》豆瓣只有3.7分。群眾紛紛表示“見過捧自己的,沒見過這麼捧自己的”。

馬保國在2008年推出《我在英國教功夫》后,又在2017年出版了《尚濟形意拳練法打法實踐》,專門為尚濟武學張目,私貨比前作少了很多。如果不是因為今年5月被50歲的民間武術家王慶民30秒內KO了3次,其製造的“武學人格”還能相對完整的保存。

無獨有偶,兩人都因為對互聯網語境的“深度挖掘”而二次翻紅。李誠儒自從上了《演員請就位》,就像豌豆射手一樣掃射了整個娛樂圈,用起成語絲毫不輸TVB編劇。流量演員見了瑟瑟發抖,就連詭辯高手小四也要被批:“小小的年紀要懂得尊重人。”

馬保國用“不講武德”的視頻虐粉,他一隻眼睛被打腫,還要義正言辭的說:“年輕人不講武德,偷襲我這個69歲的老人家,傳統功夫講究的是點到為止,點到為止他就輸了,如果我這一拳發力,一拳就把他鼻子打骨折了。”

發現沒有?李誠儒的“小小的年紀”與馬保國的“年輕人不講武德”是異曲同工的。李誠儒的炮彈,精準投放在了“流量愛豆隨意獲得S卡晉級”的現象上,成為了互聯網的犀利喉舌;馬保國的不服輸,用一種低俗喜劇的橋段引逗起大眾的嘲諷欲,發酵成二次元的狂歡。

在一段《貓和老鼠》的視頻里,湯姆貓被P上了馬保國的頭像,反覆被傑克鼠捉弄,屢敗屢戰令人捧腹。作為符號型網紅,馬保國的語錄通過互動性的儀式加強了與受眾的交流與粘合,實現了自身“永不言敗”的符號價值和內容價值的雙重深化。

浸潤了濃重江湖意識的馬保國,是心理上的弱者,卻是敘事領域的強者。對於被KO,他堅稱不將人打骨折,是出於一種仁愛之心。言下之意,他與王慶民的較量中是對方失去了道德。他之所以敗,是因為道德高尚而非技能不足。

慣用精英視角的李誠儒,選擇站在大眾這邊,為“早有公論”的焦點重申自己的看法。他說郭敬明“用廉價的筆觸來引起廣泛的共鳴”,他說陳凱歌“《霸王別姬》非常有深度,對於之後的電影也不太想去觸碰”。

網紅的內核是什麼?不正是挖掘社會轉型和文化變遷帶來的新的價值訴求嗎?馬保國發現大眾已經很久沒有嘲笑“阿Q”的快樂,李誠儒發現網友苦流量久矣,於是橫空出世並以此為內容輸出的標準。

互動儀式蘊藏着巨大的能量,當你不經意地說出“如鯁在喉”和“耗子尾汁”時,已不知不覺地被牽拉在李誠儒和馬保國的身後。

【本文作者謝明宏,由合作夥伴微信公眾號:娛樂硬糖授權發布,文章版權歸原作者及原出處所有,轉載請聯繫原出處。文章系作者個人觀點,不代表立場。如內容、圖片有任何版權問題,請聯繫(editor@zero2ipo.com.cn)處理。】

台北網頁設計公司這麼多該如何選擇?

網動是一群專業、熱情、向前行的工作團隊,我們擁有靈活的組織與溝通的能力,能傾聽客戶聲音,激發創意的火花,呈現完美的作品