[論文解讀][TinyLFU] A Highly Efficient Cache Admission Policy

image-20220504162659830

以前的問題

What is Memory Hierarchy: Definition, Diagram, Architecture and Advantages

不論是記憶體或是任何資料儲存體(或是大家常用的 Redis),都會使用 Cache 來存放短期會反覆使用到的資料。 因為 cache 具有讀取快速,但是容量相對小(且價格較貴)。所以無法將在 Physical memory 的資料全部存上,這時候就是需要有 Cache Replacement Policy (也就是「快取的取代策略」)

一般來說的做法有以下幾種:

  • FIFO (First-In First-Out): 透過先進先出的方式,往往這樣容易有相當大的功耗在於資料不斷的換進來與換出去。
  • LRU(Least Recently Used): 取代資料的時候,會去選擇近來最久的。 (RecentlyUsed –)
  • LFU(Least Frequency Used): 取代資料的時候,選擇最少被讀取到的。 (Read Count ++)

那麼這些聽起來好像都沒有問題,為什麼會需要有 TinyLFU ?

以前演算法有什麼問題。?

LRU 有什麼問題?

LRU(Least Recently Used):最近最久未使用。

它是優先淘汰掉最久未訪問到的數據。缺點是不能很好地應對偶然的突發流量。比如一個數據在一分鐘內的前59秒訪問很多次,而在最後1秒沒有訪問,但是有一批冷門數據在最後一秒進入緩存,那麼熱點數據就會被沖刷掉。

LFU 有什麼問題?

LFU(Least Frequently Used):

最近最少頻率使用。它是優先淘汰掉最不經常使用的數據,需要維護一個表示使用頻率的字段。

  • 操作 LFU 時間複查度是: \(O(log(n))\)
  • 由於取代方案取代方式是挑選短期(取決 cache 大小),來挑選最長使用的。 但是可能發生一個狀況是,如果某份資料短期不常使用,但是長期來說他頻率確是最高的。反而這個狀況會造成沒有效率。

主要有兩個缺點:

一、如果訪問頻率比較高的話,頻率字段會占據一定的空間;

二、無法合理更新新上的熱點數據,比如某個歌手的老歌播放歷史較多,新出的歌如果和老歌一起排序的話,就永無出頭之日。

那要如何解決這些問題呢?

什麼是 TinyLFU ? 是做什麼用?

image-20220504173929676

TinyLFU 解決 LRU 和LFU上述的缺點。W-TinyLFU 算法由論文《TinyLFU: A Highly Efficient Cache Admission Policy》提出。

它主要做兩件事:

一、採用 Count–Min Sketch 算法降低頻率信息帶來的空間耗損;

二、維護一個PK機制保障新上的熱點數據能夠緩存。

Count–Min Sketch 算法類似 Bloom filter 思想,對於頻率統計我們其實不需要一個精確值。存儲數據時,對key進行多次 hash 函數運算後,二維數組不同位置存儲頻率(Caffeine 實際實現的時候是用一維 long 型數組,每個 long 型數字切分成16份,每份4bit,默認15次為最高訪問頻率,每個key實際 hash 瞭四次,落在不同 long 型數字的16份中某個位置)。讀取某個key的訪問次數時,會比較所有位置上的頻率值,取最小值返回。對於所有key的訪問頻率之和有個最大值,當達到最大值時,會進行reset即對各個緩存key的頻率除以2。

TinyLFU藉助了數據流Sketching技術,它可以用小得多的空間存放頻次信息。TinyLFU採用了一種基於滑動窗口的 時間衰減設計機制 ,藉助於一種簡易的 reset 操作:每次添加一條記錄到Sketch的時候,都會給一個計數器上加 1,當計數器達到一個尺寸 W 的時候,把所有記錄的 Sketch 數值都除以 2,該 reset 操作可以起到衰減的作用 。

Sample Code

https://github.com/dgryski/go-tinylfu

這邊稍微列出相關程式碼:

關於 slru

有兩個跟著時間在移動的 list

// Cache is an LRU cache.  It is not safe for concurrent access.
type slruCache struct {
	data           map[string]*list.Element
	onecap, twocap int
	one, two       *list.List
}

來看一下 get 來了解兩個 list 的使用邏輯。

	item := v.Value.(*slruItem)

	// already on list two?
	if item.listid == 2 {
		slru.two.MoveToFront(v)
		return
	}

如果發現要找的資料在 list two ,根據 LRU 的邏輯,把它擺到最前面。

// is there space on the next list?
	if slru.two.Len() < slru.twocap {
		// just do the remove/add
		slru.one.Remove(v)
		item.listid = 2
		slru.data[item.key] = slru.two.PushFront(item)
		return
	}

不在 list two 代表他在 list one 裡面。 這時候把 list one 的 v (也就是我們要找的資料) 搬移到 list two 。

func (slru *slruCache) add(newitem slruItem) {

	newitem.listid = 1

	if slru.one.Len() < slru.onecap || (slru.Len() < slru.onecap+slru.twocap) {
		slru.data[newitem.key] = slru.one.PushFront(&newitem)
		return
	}

	// reuse the tail item
	e := slru.one.Back()
	item := e.Value.(*slruItem)

	delete(slru.data, item.key)

	*item = newitem

	slru.data[item.key] = e
	slru.one.MoveToFront(e)
}

add 邏輯相對簡單,只接從 list one 裡面放一個。

關於 TinyLFU 相關資料

https://github.com/dgryski/go-tinylfu/blob/fba88f4a7f91124e5cc36723834506b20b5bae80/tinylfu.go

type T struct {
	c       *cm4
	bouncer *doorkeeper
	w       int
	samples int
	lru     *lruCache
	slru    *slruCache
	data    map[string]*list.Element
}

關於資料結構:

  • 有兩個 cache 分別是 lruslru 。 ( slru 的內容請參考上面)
  • 資料存放在 data

Paper: https://arxiv.org/abs/1512.00727

TinyLFU: A Highly Efficient Cache Admission Policy

Gil Einziger, Roy Friedman, Ben Manes

This paper proposes to use a frequency based cache admission policy in order to boost the effectiveness of caches subject to skewed access distributions. Given a newly accessed item and an eviction candidate from the cache, our scheme decides, based on the recent access history, whether it is worth admitting the new item into the cache at the expense of the eviction candidate.
Realizing this concept is enabled through a novel approximate LFU structure called TinyLFU, which maintains an approximate representation of the access frequency of a large sample of recently accessed items. TinyLFU is very compact and light-weight as it builds upon Bloom filter theory.
We study the properties of TinyLFU through simulations of both synthetic workloads as well as multiple real traces from several sources. These simulations demonstrate the performance boost obtained by enhancing various replacement policies with the TinyLFU eviction policy. Also, a new combined replacement and eviction policy scheme nicknamed W-TinyLFU is presented. W-TinyLFU is demonstrated to obtain equal or better hit-ratios than other state of the art replacement policies on these traces. It is the only scheme to obtain such good results on all traces.

Redis 有哪一些 Cache Replacement Policy ?

參考: 93面試常問:Redis 記憶體滿了怎麼辦?

實際上Redis定義了幾種策略用來處理這種情況:

  • noeviction(預設策略):對於寫請求不再提供服務,直接返回錯誤(DEL請求和部分特殊請求除外)
  • allkeys-lru:從所有key中使用LRU演算法進行淘汰
  • volatile-lru:從設定了過期時間的key中使用LRU演算法進行淘汰
  • allkeys-random:從所有key中隨機淘汰資料
  • volatile-random:從設定了過期時間的key中隨機淘汰
  • volatile-ttl:在設定了過期時間的key中,根據key的過期時間進行淘汰,越早過期的越優先被淘汰

Reference

[電玩][NS] 黑暗靈魂 - 重製版: 手殘黨全破心得

NS Switch《黑暗靈魂重製版DARK SOULS REMASTERED》中英文美版- PChome 24h購物

前情提要:

2022 最受大家期待的遊戲,當然就是黑暗靈魂的最新開放世界最新作。 「艾爾登法環」(戲稱:艾爾登大人) 這一塊遊戲我也是第一時間就入坑(由於股癌的業配原因),買回來後當然也是相當的瘋狂的玩。短短時間我記得我已經玩了接近 80 個小時(進度慢慢打到王城)。

然後就在這個時候,因為實在很難晚上搶到電視。想說在 NS 上面也能玩一下類似「艾爾登法環」 的遊戲,就想到了我之前好像有在特價的時候把「黑暗靈魂 - 重製版」買下來,但是一下就棄坑了。 想說也用法師來重新開局黑暗靈魂看看,這一次會不會玩得比較好。 結果玩著玩著,艾爾登法環反而被我棄坑了。 我就想說專心一點把黑暗靈魂先全破,也終於在今天全破了。 這一篇只是單純把我還記得的一些東西記錄起來,也把一些我覺得很重要的偷吃步記下來。 我是沒有任何錄影啦~ 不過網路上有很多影片可以看了。

新手玩家的建議

  • 建議要法師開局,搭配萬能鑰匙。 你的人生會好很多。
  • 升等及記得先提升「持久力」跟「體力」,能活多久就看你能滾幾次,多挨個一刀。
  • 弓箭很重要,弓箭很重要,弓箭很重要。 能遠遠用弓箭射死的,絕對不要想說近戰。
  • 中後半段很重要: 記得可以斷尾的魔王,一定要斷尾。武器都超好用的。
  • 更多可以看 【心得】給剛入手黑魂re的新手們一些初期開局的建議
  • 流程可以參考 黑暗靈魂Remastered 攻略順序推薦及要點 。不要學我一開始跑去地下墓地,結果困在那邊只能重玩。

遊戲相關重點(死很大的點)

image-20220506203907785

(全破的畫面截圖,我實在不喜歡實況跟紀錄)

羊頭惡魔 - 遠遠的火焰壺偷襲

就是傳說中,真正魔王是兩隻狗。 那個羊頭惡魔只是個幌子而已。 狹小的空間加上兩隻狗一直打,基本上就是被咬好玩的。 找了影片,透過這個影片教學遠遠丟,我至少先殺死一隻狗,也讓我過了。這也卡了一兩個小時。

打到夾縫森林得時候 - 記得拿最強盔甲 - 哈維爾套裝

哈維爾套裝很重要,雖然重到不行,但是可以確保你多被打幾下。很多王我都是拿這個碾過去的。

王城雙弓

大部分會以為王城雙王很難,其實比較難得是王城雙弓。 我大概卡了三個多小時吧,每次都跑很久然後被射下去。

《黑暗之魂重製版》王城雙銀大弓簡單通過視頻教學 - 遊戲百科 …

RE:【問題】王城的黑騎士弓手要怎麼打阿 - 哈啦區

王城双弓详细打法攻略- 黑暗之魂Dark Souls - 豆瓣

深淵之王 - 無恥射死他

黑龍斷尾 - 不難打死~但是超難斷尾的。

認真打他的話大概三場可以打死,但是斷尾打了好幾個小時。不過黑龍大劍超強的物理攻擊力加上低需求,一定要來一把。

不會盾反怎麼辦 - 葛溫還是可以全破

盾反一直抓不到時機點,最後還是參考這個影片。不過這個影片技巧要求也不低,主要是因為葛溫的招式都是連續,完全沒有機會讓你有足夠精力的時間。 最後我用黑騎士套裝( CP 最好) 加上契形刺叉的消耗氣力最低,才打贏(大概也打了三個多小時),每天沒事就拿起來鍊手一下。

image-20220506203939603

image-20220506203953020

心得:

打完黑暗靈魂,終於有一種「原來我也是會玩魂系列的玩家呢!」的成就感。幾件事情分享:

  • 絕對要查攻略,病村人家說難到不行。我也是一開始就去打王,然後就不理他。 等到裝配夠強後面再來拿寶物。
  • 打不過的王一定要查,絕對有很多簡單打法。不論是拿最強盔甲來硬扛,還是遠遠射死他。
  • 打不過絕對不要氣餒,過兩天手頭順了就打很快。

參考攻略

[學習文件] 如何透過 GCP STT (Speech To Text) 與 LINE Video Flex Message 來打造幫助長輩的影片翻譯(自動輸出文字)聊天機器人

Video component example

前言:

大家好,我是 LINE 台灣的資深技術推廣工程師的 Evan Lin 。 Flex Message Update 3 在日前公佈了,除了帶來更多樣的客製化項目。 最讓人注意的莫過於可以在 Flex Message 中顯示影片元件的 Flex Message including a video 了。本篇文章將透過一個長輩使用 LINE 來跟家裡人溝通很常看到的案例,並且展示如何透過 STT 的技術來讓 Flex Message 顯示更多,更有用的資訊來幫助你。

解決的問題痛點

不知道大家是否有類似的問題,有一些長輩或是朋友們由於可能不方便打字,經常都透過語音訊息來溝通。但是許多時候其實是不方便打開手機音量來「聽訊息」或者是「看語音影片」的,比如說在捷運上,或是在會議之中。 這個時候,經常會想到說是否有一個方便的服務可以透過上傳影片(或是語音檔案)的方式。 透過 STT ( Speech-To-Text )的技術來幫影片中的語音翻譯出文字,並且透過 LINE 這次開放的 Flex Message Update 3 新格式 ,來讓使用者更快看得到你的訊息內容,而不需要打開影片內容。

如何用?如何架設? :

開源程式碼:

不囉唆,先來看 code 。

開源程式碼: https://github.com/kkdai/linebot-video-gcp

如何快速架設在自己平台:

請根據以下的流程,來直接透過開源的程式碼來架設一個 LINE Bot 跟 GCP STT 與 GCS (Google Cloud Storage) 的結合。

事前準備

開始部署

  1. 請先到程式碼: https://github.com/kkdai/linebot-video-gcp
  2. 按下: “Deploy” 來部署到你的 Heroku 帳號 image-20220421101405675
  3. 除了填寫 App Name 以外,以下的參數必須要填入才能完整運行。

    1. ChannelAccessToken: 請到 LINE Developers Console issue 一個。
    2. ChannelSecret: 請到 LINE Developers Console 拿一個。
    3. GCS_BUCKET_NAME: Google Cloud Storage Bucket Name 你需要先建立一個 GCS bucket 並且依照稍後文章的內容來改成 public access 。
    4. GCS_PROJECT_ID: Google Cloud Storage Project ID
    5. GOOGLE_APPLICATION_CREDENTIALS: 這是必須要填寫,請勿修改。
    6. GOOGLE_CREDENTIALS: 這邊請將 GCP JSON key file 的內容(對~就是整包檔案裡面的 JSON 資料),全部放上去。這樣是比較安全的。
  4. 請到 LINE 官方帳號的平台,到了右上角的「設定」中,選擇「帳號設定」
    1. 將你官方帳號基本資料設定好,並且打開加入群組功能。
      1. image-20220421103018014
    2. 到回應設定,將以下設定改好:
      1. image-20220421103154889
      2. 回應模式改成「聊天機器人」
      3. 停用「自動回應訊息」
      4. 啟用「Webhook」
    3. 到 Messaging API 選項,將 Webhook 網址填入`: https://{YOUR_HEROKU_SERVER_ID}.herokuapp.com/callback
    4. 關於如何快速部署的流程,可以參考另外一篇文章內的影片:

如何使用:

  • 打開聊天機器人
  • 傳送影片訊息
  • 過一兩秒的判別時間,就會收到結果的 Flex Message

成果

image-20220407212250046

開發流程記錄:

這邊透過一些開發流程,來跟各位分享該如何在 LINE 聊天機器人中來完成這樣的開發:

如何在 Heroku 上面開發 Golang 的 App

image-20220412143245984

以往的時候,如果要使用 Google Cloud 相關的 API (比如說: Google Cloud Storage) 存取 API ,只能透過 JSON 檔案來操作。但是如果你想要放上 Heroku 的時候,就必須要放上 GitHub ,這個時候就很容易不小心誤放 JSON 檔案而被機器人掃走而盜用。透過環境變數跟 Golang Buildpack 可以幫助你在安全無慮的狀況下部署 Herokuu 專案,也可以開源到 Github ,歡迎參考這篇文章

以下也提供一個簡單的測試程式碼,可以確認連接到 GCP 是否有正確連結。

如何投過官方帳號 (Official Account) 來抓取 LINE 聊天對話中的影片或是聲音檔案

首先,當官方帳號收到圖片訊息(image),影片訊息(video) 或是聲音訊息(audio) 的時候,通常會透過以下幾個 Message Hook.

以 Video Message Webhook 為例子,你會看到以下的例子(來自 LINE Dev Doc)

image-20220411171226450

  • 如果 Video Message 的影片提供者是外部服務,可能還可以取得檔案的連結。
  • 但是如果你透過上傳影片給官方帳號,你可能會發現官方帳號無法直接存取到檔案內容。需要透過 Get content 的 API 來取的相關資訊。

以下提供範例的 Golang 程式碼,來展示如何取得上傳到 LINE 平台的影片檔案內容:

這個方式就可以取得檔案的 IO Reader 內容,就可以透過 content 這個 IO Reader 來將檔案抓下來,或是直接上傳到 Google Cloud Storage 。

如何將檔案上傳到 Google Cloud Storage

先看程式碼,以下幾件事情要注意:

  • 需要有 cancel 的 context 避免上傳時間過久,造成 API Error 。
  • 依照前一個檔案範例,其實可以直接拿 bot.GetMessageContent(message.ID).Do() 裡面的 content IO Reader 來使用。不需要真的下載到本地端後,再上傳到 GCS 。
  • 上傳到 GCS 的檔名,建議不要重複了。 可以使用以下方式來產生唯一的名字。

上傳到 GCS 之後,就可以進入下一個階段,將檔案送到 STT 服務 - Google Speech-To-Text 來判斷。

如何將讓 STT 服務來判斷檔案裡面的文字

透過 STT console 線上測試你的檔案

image-20220413163042927

這裡以 Google Speech To Text 為例子,先到控制台打開相關服務後到 Speech Console 。並且可以在控制台上直接上傳測試一段小影片,這邊有幾個參數可以解釋一下:

  • 檔案選擇上,可以 選擇 MP4 來作為 STT 的判斷檔案,只要 Audio Encoding 選擇正確就好
  • Encoding :記得選 MP3, 不然通常都會有問題。 iPhone 手機都是 MP4 container 加上 MP3 Audio Encoding 。
  • Sample Rate : 記得選 48000

image-20220413163735523

下一個項目也有一些可以調整:

  • Spoken language: 記得選 zh-TW ,除非你講英文錄影。
  • Transcription model:選擇 Default 其實就很夠用。

以上流程大概就是一個讓你透過 Console 來測試你的音訊檔案,這邊有幾件事情可以注意到。

  • Google STT 可以直接吃影片檔案,不用自己跑音訊擷取。
  • Google STT 可以直接吃影片檔案,不用自己跑音訊擷取。
  • Google STT 可以直接吃影片檔案,不用自己跑音訊擷取。

並且要注意你的 Sample Rate 不要挑選錯誤。才能讓聲音正確被讀取到。

使用 Go GCP STT SDK 來判斷

首先要使用 Speech To Text 的 client API 來處理內容,需要有一個檔案位置。 為了讓網路處理比較快速,這裡改用 Google Cloud Storage 內部的 File URI 的方式。可以參考以下組成方式:

	// The path to the remote audio file to transcribe.
	fileURI := fmt.Sprintf("gs://%s/%s", c.bucketName, c.objectName)

接下來跟大家分享一下部分的程式碼:

這邊有些重要的事情跟大家分享:

1. 必須使用 beta SDK 才能支援中文與 MP3

// Must use "apiv1p1beta1" version to enable support on Chinese and MP3
speech "cloud.google.com/go/speech/apiv1p1beta1" //v1p1beta1
speechpb "google.golang.org/genproto/googleapis/cloud/speech/v1p1beta1" //v1p1beta1

目前 Golang 的 Speech SDK 尚未支援中文,所以必須要使用 beta1 的才能找到中文支援! 目前 Golang 的 Speech SDK 尚未支援中文,所以必須要使用 beta1 的才能找到中文支援! 目前 Golang 的 Speech SDK 尚未支援中文,所以必須要使用 beta1 的才能找到中文支援!

這邊依據了這篇文章有提到,終於讓我找到解決方式。 「iThome 鐵人賽 - Day 23 Google Cloud Speech-to-Text - 子系列最終章

2. 關於 STT 的設定

這邊已經透過 STT 控制台針對經常出現的檔案來測試,所以得出了以下的相關設定

Config: &speechpb.RecognitionConfig{
			Encoding:        speechpb.RecognitionConfig_MP3,
			SampleRateHertz: 48000,
			LanguageCode:    "zh-TW",
		}
  • Encoding: 指的是音樂壓縮的格式,請注意只有 v1p1beta1 才支援 MP3

  • SampleRateHertz: 取樣的 sample rate ,手機跟相機通常都使用 48000

  • LanguageCode: 這邊是指 STT 使用的 Model 語言包,請注意只有 v1p1beta1 才支援中文 zh-TW

3. 關於結果的使用

// Prints the results.
	var resultStr string
	for _, result := range resp.Results {
		for _, alt := range result.Alternatives {
			log.Printf("\"%v\" (confidence=%3f)\n", alt.Transcript, alt.Confidence)
			resultStr = resultStr + alt.Transcript + " "
		}
	}

回傳的一系列的結果,並且有附上信心度。所以要一個個找出來處理。這邊有些東西建議要特別處理:

  • resp.Results 有可能是空的(因為沒有適當的答案),使用上需要特別處裡 empty case 。
  • 使用答案前,記得要看一下信心度是否夠高。

如何取得 GCS 對外的公開位置

打開分享權限

建議透過介面打開來權限

  • 到 Console 到擁有 Google Cloud Storage 的專案
  • 透過 More Button 打開 Edit Access

image-20220408105439200

注意事項:

  • 如果你想透過 code 來改權限,請不要使用一個個檔案來打開。會出錯。 (這段在最近使用就會有問題
  • 打開一次資料夾權限,之後不需要再調整。

取得公開對外的檔案位置

已經修改資料夾權限,讓他可以 Public 後。如何取得 Google Cloud Storage 對外鏈結呢?

規則如下:

https://storage.googleapis.com//

所以可以寫成一個簡單的 function ,來幫你產生。

如何發送 Video Flex Component Message

image-20220418125020910

這邊的 Video Componet Flex Message 格式如下:

  • Hero 本體有一個 Video Component ,並且上面有 「 More Information 」可以讓開發者連結到更多資訊的網站。可以是官方網站,或是相關的說明。
  • 下面 Body 中有文字有兩段,其中有翻譯的內容。

這邊給大家一些經驗分享:

  • 如果影片沒有 PreviewURL 可以先給一個範例,使用者播放一次影片後,會出現正確的 Preview 。
  • 如果有 TextComponent 要特別處理 empty 的 case ,不然會造成以下類似的 error message :
> 2022/04/13 06:19:44 linebot: APIError 400 A message (messages[0]) in the request body is invalid
> [/body/contents/1/contents/1] invalid text content
>  [/body/contents/1/contents/1] `text` or `contents` must be specified
  • 由於 Google STT 需要超過一分鐘左右的存取跟偵測的時間,建議使用 PushMsg 來回覆這則訊息。
  • 在訊息的目標方面,針對群組(聊天室)需要有特殊處理:
				// Determine the push msg target.
				target := event.Source.UserID
				if event.Source.GroupID != "" {
					target = event.Source.GroupID
				} else if event.Source.RoomID != "" {
					target = event.Source.RoomID
				}

這樣就可以完成相關的工作,請大家可以來透過開源的程式碼自己來部署。 https://github.com/kkdai/linebot-video-gcp

相關技術文件:

未來相關工作

這一篇文章透過大家經常聽到的功能 STT (Speech-To-Text) 結合這一次 Flex Message Update 3 released 所更新的新功能 Video Component ,希望可帶給大家更多的想法,進而開發出更多可以幫助使用者的工具。

其實有更多的點子可以讓大家一起來協作,比如說:

  • 透過 OA 自動上字幕的功能
  • 透過 Video Component 讓廣告文字變得更生動,因為上面有客製化選單,如何讓使用者透過 Video 跟影片互動變成遊戲也變成一個方式。也是一個很值得思考的。

如果你有任何建議或是疑問,歡迎透過 LINE Developers 的官方討論區或是LINE 開發者官方社群的官方帳號跟我們聯絡

LINE Developers 相關技術文件與部落格:

[好書分享] 社會在走,歷史要懂-呂捷開講


社會在走,歷史要懂-呂捷開講
作者: 呂捷  
插畫: 蠢羊  
出版社:圓神出版 
出版日期:2021/09/01 

買書推薦網址:

前言:

這一本是今年所讀完的第七本書。呂捷是知名的補教名師,我也是在網路文章跟一些節目中有聽過他的大名。畢竟網路上經常在瘋傳他講歷史課生動有趣的樣子。想說就買這本來看看,當作我平常手邊的閒書之一(也就是看書看累了,調劑身心用的書)。

內容簡介與心得:

歷史總是不斷重演,人性更是不分朝代國籍,相似得可怕,
呂捷不僅帶你讀通歷史脈絡,更看懂那些古人用血淚教你的事。
禪讓,真的這麼一回事嗎?商紂王真的有那麼壞嗎?周幽王真的是放煙火放倒的嗎?
本書從傳說時代開始,走過三皇五帝、歷經夏商周,及至諸子百家爭鳴。最擅長講古的歷史名師呂捷以豐富的故事、輕鬆有哏的鄉民語言,讓你讀通遠古時期到文化奠基時期。
聽呂捷老師開講,歷史不再是破碎的片段文字,而是一部高潮迭起的小說,不用死背也牢記不忘。古人的人生歷練,更彷彿一部社會生存說明書,讓你讀史,更讀懂真實世界生存之道。

章節條列

第1章 這不是歷史是考古:史前時代
第2章 傳說不只是傳說:三皇五帝與夏
第3章 史上第一次革命:商湯伐桀
第4章 制禮作樂定江山:西周
第5章 亂世出英雄:春秋戰國
第6章 真正的自由中國:諸子百家爭鳴

所有的章節裡面從史前時代開始講解,提到了堯舜禹湯。 並且也提到一些跟文學有關的常識,比如說「三過家門而不入」,因為文學裡面的「三」是虛數,代表的是很多的意思。 而且也提到了說,堯在為一百一十八歲,舜在為八十三年。也就是代表當初的堯跟舜並不是兩個人,而是兩個部落的意思。 這一類的小知識也讓我們更了解了中國歷史上的由來。

除了文學之外,歷史上面也有許多有趣的相關分享。 比如說占星術跟算命,遠從商朝的天文曆法就開始。商朝發明了天干地支,並且有了農民曆法跟閏月。

除了文學跟相關占星術之外,作者也引用了許多有趣的故事。比如說商紂因為寵愛妲己,妲己喜歡帥氣的姬考但是被拒絕。 因而跟紂王告狀造成將姬考剁成肉醬餵食給周文王,也就造成了後續的周朝推翻商朝的主因 (帥氣真不好 XD) 。

春秋戰國是中國一個很重要的時代,許多的思想開始萌芽,百家爭鳴。 裡面也有許多有趣的成語故事分享:

  • 齊桓公跟管仲的一箭之仇。
  • 晉文公的退避三舍
  • 齊師伐魯裡面子貢擔任說客的內容

這三段小故事絕對跟你想像中的不同,也真的是很有趣的敘事方式。

心得

這本書很像集結了呂捷充滿幽默的史料內容,並且把大家都耳熟能詳,但是真正的史實會讓你嚇一跳的有趣內容。 並且呂老師很懂得透年輕人的對話(常見的鄉民對話,電玩,漫畫)的內容來讓整本書讀起來欲罷不能。 讓你邊笑邊了解許多有趣的歷史故事。很推薦給大家好好的了解一下。

[好書分享] 我45歲學存股,股利年領200萬: 投資晚鳥退休教師教你「咖啡園存股法」,讓股市變成你的搖錢樹

我45歲學存股,股利年領200萬: 投資晚鳥退休教師教你「咖啡園存股法」,讓股市變成你的搖錢樹
作者: 謝士英  出版社:采實文化 
出版日期:2020/06/28

買書推薦網址:

前言:

這一本是今年所讀完的第六本書。 謝士英老師也是我在 YT 上面看到的老師,我覺得他講存股概念淺顯易懂之外,又相當的實在。不會有許多複雜艱深的道理,滿滿的都是容易的存股操作與投資上的心理建設。 所以我買了這一本書,想要來了解作者的投資理念。

內容簡介與心得:

45歲以前,完全不懂投資的高師範工業科技教師謝士英,
2000年,受到《富爸爸,窮爸爸》一書和傻瓜投資法的啟發,才開始學投資。

45歲那年,謝老師立志50歲破千萬,
第一年以220萬元本金投資,
第二年變440萬元,
第三年變880萬元,
三年半就變1,000萬元,
不到五年的時間,就提早實現目標。

這麼厲害,他是怎麼辦到的?

謝老師立志學投資後,開始鑽研傻瓜投資法,
他發現,這種懶人、不動腦的投資法,就是源自於巴菲特的價值投資,
也從中淬鍊出自己的一套存股成功法「咖啡園存股法」。

一般人買股票就像買咖啡樹,等咖啡樹漲價就賣掉,賺價差。
而存股就是種植咖啡樹後,好好照料、呵護,等咖啡樹結果,生產咖啡豆,
再把賣出咖啡豆的錢買另外兩棵咖啡樹,
久而久之,咖啡園的咖啡樹就越來越多,多到有一天咖啡喝不完也賣不完。

章節條列

第1章 45歲學存股,三年半滾出千萬

「窮爸爸富爸爸」開啟了作者理財之路,那時候開始看股票。 第一張股票買了中鋼,開始了相關的理財之路。起始資金是 200 萬,開始時間是 2000 年左右。

第2章 咖啡園存股法,讓股市成為搖錢樹

第3章 咖啡園存股法的買賣原則

作者舉了一個下金雞蛋的母雞的故事作為範例,從今有一個下金雞蛋的幾,每天都會下一顆金雞蛋。但是有一個貪心的人把雞殺了,卻發現他身體裡面不是金子,卻反而虧大了。 作者把股票帳戶當做咖啡園一樣,要有耐心的種,讓他不斷的產生新的咖啡豆下來。 不要急著把咖啡樹砍掉。裡面幾個概念如下:

  • 咖啡樹不會馬上咖啡豆產出,要有點耐心等待。
  • 不少人把咖啡樹直接去買賣(作價差),這需要相當的時間跟許多手法,不是作者推薦的。

投資好公司的理由:

  • 維持一致的獲利能力:可以持續,並且在本業內好好賺錢。
  • 良好經營團隊
  • 持續競爭力
  • 簡單易懂的企業:買自己懂的企業
  • 董監持股大於 10%

什麼理由買進,就要用什麼理由賣出。

這是一個很重要的概念,作者也提到了除非是以下幾個理由,不然不會有賣出咖啡樹的理由:

  • 公司變壞了
  • 更好的標的
  • 貴了

第4章 存股實戰心得分享

關於統一存股的經驗分享:

  • 作者本來想買統一超,但是統一超太貴。統一相關企業做得很好,成為長久持股之一。
  • 太平洋建設買了之後發生風災,造成許多房子的問題。加上公司內部不穩定,決定賣出。(公司變壞了)
  • 投資標的不要太多,才能挑選出好公司。
  • 收到股息,持續投入。產生可觀的複利效果。

第5章 打造存股體質的致富觀和好習慣

  • 要有良好的理財觀念
  • 存錢要趁早,複利效果才會更強
  • 穩定的賺錢是安全的,別嫌慢
  • 製造被動收入,讓收入能源源不絕。
  • 訊息要有自我檢查的習慣,不要聽信電視及報導就買進或是賣出。
  • 有機會了解公司,多聊一點來認識一家好公司。
  • 不要天天盯盤,但是要審視自己投資公司的本質。

第6章 如何安然度過每次股災?

遇到股災的時候,許多散戶都會想要趕快入袋為安。但是往往就已經吃到許多的虧損,卻在平倉的時候平在最低點。成了賣在阿呆股。

  • 股災發生的時候,持續檢視手邊公司體質,是否有變差。
  • 因為無法知道會跌到什麼地步,不要隨意平倉。只賣出體質變差的公司。
  • 體質好的公司趁低價持續加碼,增加咖啡園的咖啡樹。
  • 不要隨便擴張信用,如果你連現金跟現股都無法保證獲利,那麼擴張信用只會讓你面臨更大的風險。
  • 要有「最壞的打算」

心得

這一本書沒有複雜的技術線教學,沒有太多基本面的分析理念。但是有許多關於作者本人對於投資的經驗談與想法。作為 45 歲才開始投資的人,裡面有許多清楚又淺顯易懂的操作手法。很適合沒有時間,或是像我一樣本身也是很後期才開始學投資的人。

作者經常透過咖啡樹的舉例,來講解關於存股的基礎概念。也透過對於好公司與壞公司的了解,來決定要再下跌的時候加碼還是要賣出。這一些基礎但是又常常被人遺忘的操作手法,其實對於散戶的心理建設相當的重要。很推薦跟我一樣無法全心看盤,但是想要做存股想法的人來看。

[學習文件] 如何在 Heroku 上面使用透過 Golang 來存取 Google Cloud 服務

image-20220321200254901

前言:

以往的時候,如果要使用 Google Cloud 相關的 API (比如說: Google Cloud Storage) 存取 API ,只能透過 JSON 檔案來操作。但是如果你想要放上 Heroku 的時候,就必須要放上 GitHub ,這個時候就很容易不小心誤放 JSON 檔案而被機器人掃走而盜用。

本篇文章將告訴你,透過環境變數跟 Golang Buildpack 可以幫助你在安全無慮的狀況下部署 Herokuu 專案,也可以開源到 Github 。

流程:

其實這一篇 Adding Google Cloud Credentials to Heroku 的內容算是蠻完整的,但是裡面的 buildpack 最近用起來怪怪的。

  1. 開啟一個專屬的 services account

    1. 透過 Google Cloud Console https://cloud.google.com/storage/docs/reference/libraries#create-service-account-console

      image-20220321204811895

  2. 設定好需要的權限就好: (圖片是需要 Cloud Storage 的建立者)

    image-20220321205120799

  3. 下載你的 JSON Key (檔案請妥善儲存)

    image-20220321205220312

  4. 透過 golang build pack 新增

    heroku buildpacks:set https://github.com/gerywahyunugraha/heroku-google-application-credentials-buildpack -a your-app-name
    
  5. 接下來將 JSON 檔案參數填寫進 Heroku 設定

image-20220321204425338

GOOGLE_APPLICATION_CREDENTIALS: google-credentials.json (固定)
GOOGLE_CREDENTIALS: 裡面放 JSON 完整內容。
  1. 相關程式部分:

相關文章: