MongoDB 3.4 Sharding 觀念、安裝、與配置

Sharding 為 MongoDB 所擁有的一種資料分散處理架構,簡單的說就是將資料分片 (Shard) 儲存到不同的機器中,最常應用在大數據的案例上。在海量資料的儲存情境上,垂直擴充架構是無法滿足的,必須透過水平擴充來實現。

MongoDB Sharded Cluster 基本的架構示意如下:

在這樣的機制下,儲存進 Collection 的資料會被盡可能平均地分散到每一個 Shard 上,每一個 Shard 都是由獨立的 mongod 實體或者 Replica Set 所構成 (想了解 Replica Set 可以看看之前的文章)。上圖我們也可以看到,Sharding 機制本身是不負責備份的,在產品上線的環境中,強烈建議使用 Replica Set 來搭建 MongoDB Sharded Cluster。在這個架構中,假設我們有 1TB 的資料,可以透過 Sharding 機制將資料切分為四個 Shard,每一個 Shard 負責儲存 256G,應該很好理解。

MongoDB Sharded Cluster 運作機制

那麼 MongoDB Sharded Cluster 是如何運作的呢?我們先看看下面的架構圖:

當使用者或應用程式 (Driver) 要操作 MongoDB Sharded Cluster 時,是透過 mongos 來進行連接,mongos 扮演 Router 的角色,Router 通常由多個實體組成,可以將 Loading 分散處理,保持高可用性 (HA)。對於應用程式來說,並不需要瞭解 MongoDB Sharding 怎麼運作的,他們看到的只是一個資料庫,所以使用上基本不會有太大的差別。如下所示:

之前提到,雖然每一個 Shard 都是由一個 mongod 或 Replica Set 構成,但如果沒有透過 mongos (Router) 進行連線操作,而直接對 Shard 進行連線,那麼你看到 Collection 的資料就不會是完整的集合,而只是單一個 Shard 的資料。那麼 Cluster 是如何分配資料呢,這裡有一個很重要的角色,就是 Config Server。

Config Server

Config Server 是 MongoDB Sharding 架構中相當重要的一個角色,它存放了資料的 Metadata,包括透過 Shard Key 計算出來的索引,用來記錄每一個資料存放的 Shard 位置,好讓 Router 可以正確的 Query 資料,如果沒有這些索引,那麼每一個用來存放資料的 mongod 實體,就「純粹」只是獨立存放分散的資料,無法協同工作。Config Server 聽起來很重要對吧!?因此 Config Server 部署時必須要多台機器,在新版 3.2 之後也可以用 Replica Set 架設 Config Server。

為了將資料分散儲存,就必須找一個方法來管理 Index,我們必須將 Document 某一個欄位定義為 Shard Key,然後透過 range based partitioning 或 hash based partitioning 其中一中方式將資料分配到 chunks 中 (每一個 Chunks 預設的大小為 64MB),最後才將 Chunks 分散到不同的 Shard 上。接下來我們先看看兩種不同的 Partitioning 機制:

Range Based Sharding

這種方式就是將 Document Shard Key 欄位的值,以線性的方式進行分群,透過 Range 範圍進行切割,相近的值理所當然會被分到同一個 Chunk 中,Chunk 分配的情況會直接受到 Range 的影響(比如某一段 Range 出現頻率高,Chunk 資料就比較大)。用這種方法我們必須考慮 Shard Key 的範圍,如下所示:

Hash Based Sharding

這種方法顧名思義就是透過「雜湊函式」將我們指定的 Shard Key 欄位進行雜湊,這樣的方式資料比較容易分散到每個 Shard 中,如果資料量足夠豐富,佔用空間的分配也會比較平均。如下:

比較一下兩種方法,Range Based 實際在 Query 時,Router 可以很輕易地判斷資料的位置,然後正確地派送運算到所屬的 Shard 上。但如果要查詢的資料片段大小差異過高,且又分散在不同的 Shard 上,查詢必定會「等待」其他 Shard 處理的情況產生。來看看 Hash Based,Shard Key 透過 Hash 計算後,很容易分散在不同的 Chunk,資料分散性佳,擴充也比較容易。但是在 Query 時就必須要經過比較多的 Shard 計算,才能由 Router 返回最後的結果。兩種方法各有利弊,可以依照實際的應用情況選用。那如果想要自行實作資料分散的邏輯呢?MongoDB 當然也是支援的,就是透過 Tag 這個功能,但我沒有研究,所以就無從介紹了。有興趣可以看看官方 Tag Aware Sharding 相關介紹。

開始建置:

由於 Shard 本身沒有備援機制,因此 MongoDB 的 Shard 必須建置在 Replica Set 上,Replica Set 建置方式請參考「MongoDB Replica Set 高可用性架構搭建」這一篇文章。假設您已經建立好 Replica Set,那麼就可以繼續接著開始建置 Shard。

我們規劃原來做的mongsh1~mongsh3三台伺服器,都拿來做shard server與config server,另外mongsh1/mongsh2拿來當router。

建置 Config Server

一開始我們先建立 Config Server,在 MongoDB Sharding Cluster 架構中,Config Server 必須有三個實體以上,強烈建議部署在不同的機器上,因為 Metadata 實在太重要了。下面的範例其實是與 Replica Set 一起部署,實際上分開會比較好。慣例上我們會先透過 /etc/hosts 管理我們的主機資訊 (用 DNS 也是可以),假設要安裝 Config Server 的 Hostname 為 mong-cfg1 ~ mong-cfg3

vi /etc/hosts
10.21.1.45 mongsh1
10.21.1.46 mongsh2
10.21.1.44 mongsh3

10.21.1.45 mong-cfg1
10.21.1.46 mong-cfg2
10.21.1.44 mong-cfg3

10.21.1.45 mong-router1
10.21.1.46 mong-router2

接著建立 Config Server 要存放的 DB File Directory,命令如下:

mkdir -p /home/mongodb-cfg
sudo chown -R mongodb:mongodb /home/mongodb-cfg

三台伺服器都要做。

然後建立 MongoDB Config Server 需要的設定檔,之後再透過 mongod 來載入啟用,因為我們測試環境的 Config Server 與 Replica Set 都在其實同一台機器(正式環境建議分開或分散比較好),Port 與 PID 都要不同,Port 隔開可以方便我們部署在不同機器,然而透過不同的設定檔也會比較好進行管理。大致上的 Port 分配如下:

  • Replica Set:27019 Port
  • Config Server:27018 Port
  • Mongo Router (mongos):27017 Port

編輯 Config Server 設定檔內容如下:

vi /etc/mongod-cfgserv.conf
storage:
  dbPath: /home/mongodb-cfg
  journal:
    enabled: true
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod-cfgserv.log
sharding:
   clusterRole: configsvr
net:
  port: 27018
  bindIp: 0.0.0.0
processManagement:
  fork: true
  pidFilePath: /var/run/mongod-cfgserv.pid

上面的設定檔先不開啟認證模式,官方規定在 Production 環境最少要配置三台以上的 Config Server。透過以下 mongod 命令分別在「mong-cfg1, mong-cfg2, mong-cfg3」三台機器各別透過 mongod 指令來啟用 Config Server。

sudo mongod -f /etc/mongod-cfgserv.conf

啟動後我們也可以在 /var/log/mongodb/mongod-cfgserv.log 看到 log 資訊。

建置 MongoDB Router

再來就是建置 MongoDB Sharding Router。首先建立 mongos 要載入的設定檔,基本上跟上面 Config Server 使用的 mongod 差不多。我們這裡測試用的 Router 是跟 Config Server 放在一起,實際上可分開存放會更好。

這裡,我們就都不設定認證模式,若有意設置,可參考這篇文章

設定檔內容如下:

sudo vi /etc/mongod-router.conf
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod-router.log
sharding:
  configDB: mong-cfg1:27018,mong-cfg2:27018,mongodb-cfg-3:27018
net:
  port: 27017
  bindIp: 0.0.0.0 
processManagement:
  fork: true
  pidFilePath: /var/run/mongodb-router.pid

我們可以看到上述的設定檔有指定 Config Server 的位置,好讓 Router 啟動時可以讀取 Config Server 中的 Metadata。也需要配置到另外一台伺服器mong-router2

如同上述的設定檔,先不用啟用認證來執行 mongos,主要是為了要先在 Config Server 中建立 User 好讓後續整個認證流程可以順利串起來,這裡通常大家都會遇到最多問題,很多人最後乾脆關閉認證來配置 Sharding,這樣其實很危險,不建議關閉認證。此外由於應用程式大多是透過 27017 Port 進行連線,所以要提供連線的 Router Bind 直接啟動在標準 MongoDB Port 這樣應用程式就不用修改囉。

先啟用其中一台的 MongoDB Sharding Router,等透過 Mongo Router 設定好 Config Server 之後再啟動所有的 Rouer 即可。注意這裡是用 mongos 命令來啟動喔,如下:

sudo mongos -f /etc/mongod-router.conf

配置自動啟動config與router服務:
於10.21.1.45與10.21.1.46兩台伺服器

vi /etc/rc.local
mongod -f /etc/mongod-cfgserv.conf
mongos -f /etc/mongod-router.conf

於10.21.1.44則配置如下

vi /etc/rc.local
mongod -f /etc/mongod-cfgserv.conf

建立 Sharding Cluster

接著我們透過認證模式進入 Mongo Router 來設定 Sharding,因為後端的 Monogd 是採用Replica Set 認證模式,所以配置 Sharding 的動作一定要透過同一把 Key 啟動,才能把服務整個串起來。以下透過我們建立好的管理者帳密登入 Mongo Router 來進行配置:

mongo mongodb-router1
mongos>sh.addShard("bes/mongodb-a1:27019,mongodb-a2:27019,mongodb-a3:27019")

加入後,再檢查一下狀態:

mongos> sh.status()
--- Sharding Status --- 
  sharding version: {
	"_id" : 1,
	"minCompatibleVersion" : 5,
	"currentVersion" : 6,
	"clusterId" : ObjectId("59b4e7b564bf31ba36e4615c")
}
  shards:
	{  "_id" : "bes",  "host" : "bes/mongsh1:27019,mongsh2:27019,mongsh3:27019",  "state" : 1 }
  active mongoses:
	"3.4.8" : 2
 autosplit:
	Currently enabled: yes
  balancer:
	Currently enabled:  yes
	Currently running:  no
		Balancer lock taken at Sun Sep 10 2017 20:27:09 GMT+0800 (CST) by ConfigServer:Balancer
	Failed balancer rounds in last 5 attempts:  5
	Last reported error:  Cannot accept sharding commands if not started with --shardsvr
	Time of Reported error:  Wed Sep 13 2017 11:18:59 GMT+0800 (CST)
	Migration Results for the last 24 hours: 
		No recent migrations
  databases:
	{  "_id" : "teammerge12",  "primary" : "bes",  "partitioned" : true }

mongos> 

實務的配置上,我們會部署多台 Router 來平衡應用程式端的查詢,在應用程式中也可以指定這一群「Router」作為 Server。到這裡 MongoDB Sharding Cluster 就算是被置完成囉,實際的使用上還需要指定 Collection Shard Key 來分配 Chunk 到不同的 Shard 上,這裡請自行參考 MongoDB 官方的 Shard Key 使用介紹。

GeoIP installation for PHP on Ubuntu 16.04

Installing GeoIP Module On Apache2, Ubuntu 16.04

  1. 以下面這個指令尋找Geoip的相關程式:
    apt search geoip
    

    將會從相關的套件裡找到 libapache2-mod-geoip

  2. 進行套件安裝與更新
    apt update
    apt upgrade
    apt install geoip-bin geoip-database libapache2-mod-geoip libgeoip1
    

    新增後,會產生 /usr/share/GeoIP/ 目錄。

  3. 下載GeoIP資料庫
    cd /usr/share/GeoIP/
    ls
    rm GeoIP.dat
    wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
    gunzip GeoIP.dat.gz
    wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
    gunzip GeoLiteCity.dat.gz
    wget http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz
    gunzip GeoIPASNum.dat.gz
    

    在 /usr/share/GeoIP/ 目錄裡,會有三個檔案GeoIP.dat, GeoLiteCity.dat, GeoIPASNum.dat。

  4. 更新apache2的geoip設置:nano /etc/apache2/mods-enabled/geoip.conf
    GeoIPEnable On
    GeoIPDBFile /usr/share/GeoIP/GeoIP.dat
    GeoIPDBFile /usr/share/GeoIP/GeoLiteCity.dat
    GeoIPDBFile /usr/share/GeoIP/GeoIPASNum.dat基本上就已經設定完成。
  5. 重新啟動apache2
    apachectl -t
    sudo systemctl restart apache2.service

最後做一個範本試試看:

<?php 
$geoip_country_code = getenv(GEOIP_COUNTRY_CODE);
$geoip_country_name = getenv(GEOIP_COUNTRY_NAME);
$geoip_region = getenv(GEOIP_REGION);
$geoip_city = getenv(GEOIP_CITY);
$geoip_postal_code = getenv(GEOIP_POSTAL_CODE);
$geoip_latitude = getenv(GEOIP_LATITUDE);
$geoip_longitude = getenv(GEOIP_LONGITUDE);
 
echo 'Country code: '.$geoip_country_code.'&lt;br&gt;';
echo 'Country name: '.$geoip_country_name.'&lt;br&gt;';
echo 'Region: '.$geoip_region.'&lt;br&gt;';
echo 'City: '.$geoip_city.'&lt;br&gt;';
echo 'Postal code: '.$geoip_postal_code.'&lt;br&gt;';
echo 'Latitude: '.$geoip_latitude.'&lt;br&gt;';
echo 'Longitude: '.$geoip_longitude.'&lt;br&gt;'; 
?>

大功告成!!

MongoDB Replica Set設置,採用MongoDB 3.4

安裝MongoDB 3.4 for CentOS 7

vi /etc/yum.repos.d/mongodb.repo
mongodb-org-3.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc

然後在執行

yum install -y mongodb-org

另外,需要將selinux(/etc/selinux/config)設定為SELINUX=Passive或Disable,詳細可參考:
https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-hat/

MongoDB Replica Set介紹

MongoDB 算是一個很發展非常成熟的專案,大多數的系統裝起 MongoDB 應該都不會有太大的困難,今天介紹一下進階一點點的用法,Replica Set。資料庫系統做高可用 Replication (副本) 模式算是很常見的架構,在大陸稱為「主備模式」主要提供一份資料庫即時映射的副本,好讓主要的服務資料庫發生異常時可以接手工作。同時,另一個優勢就是可以進行資料備援,或者用來進行查詢。此外,當資料庫大到一定的程度,傳統的 dump 工具將很難完成任務,備援的方法就可以靠 Replication 來完成。

現在的 Open Source 系統發展得很快,官方提供的版本就早已經支援 Replication,想想以前的 PostgreSQL 在 5.x 的時候還要自己 Patch 第三方 Project 進行編譯,比起來真的省事多了。

官方有提供三種 Replica Set 架構 (Pattern),如下:

  • Three Member Replica Sets
  • Replica Sets with Four or More Members
  • Geographically Distributed Replica Sets

第一種 Three Member Replica Sets 是最常用的架構,由三個 MongoDB 節點組成,每個節點其實都是 Mongod 服務。第二種由更多的節點組成,備援能力更強,但我沒有研究,無從介紹。最後一種 Distributed Replica Sets 主要滿足異地備援的需求,這個聽起來不錯。

今天來介紹 MongoDB 最典型的副本架構,主要由三個節點構成,如下:

正常情況對 Primary 節點進行讀寫,資料會自動複製 (Replication) 到另外兩組 Secondary 節點,這些節點彼此透過 Heartbeat (每隔一段時間試探節點是否存活的方式) 檢測狀態,正常的情況每 2 秒會送出 Heartbeat,若是超過 10 秒沒有回覆,那就是 GG 了。如下:

當主要連線的節點發生故障時,會選出一台 Secondary 成為 Primary 接手工作,這樣的能力稱為 Automatic Failover,如下:

安裝與設定MongoDB Replica Set

大概知道工作原理以後,那麼我們來看看如何設定 Replica Set 架構。

開始之前我們先在 /etc/hosts 定義這三台要安裝的 hostname 與 IP Address,當然如果您想透過 DNS 服務來管理也是可以的。

vi /etc/hosts
10.21.1.45 mongsh1
10.21.1.46 mongsh2
10.21.1.44 mongsh3 

建立一個讓 Replica Set 專用的全新資料庫目錄

mkdir -p /home/mongod
chown -R mongodb:mongodb /home/mongod

三台伺服器皆需要做此設定,以方便確認資料庫的目錄以及位址。

設定 Replica Set 服務的 Mongod 設定檔(先不啟用驗證模式)

vi /etc/mongod.co
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log

storage:
  dbPath: /home/mongod
  journal:
    enabled: true

processManagement:
  fork: true  
  pidFilePath: /var/run/mongodb/mongod.pid  # location of pidfile

net:
  port: 27019
  bindIp: 0.0.0.0  

這裡我們將 Replica Set 服務設定在 27019 Port,主要是因為之後會繼續建立 Sharding 架構,刻意避開標準的 27017 Port,保留 27017 Port 給之後的 Mongo Router 使用。如果您不打算建構 Sharding,那就直接使用 27017 即可,讓應用程式端不需要修改就可以使用。修改完設定檔後記得重新啟動 mongod 服務:

systemctl start mongod

先連線進到第一台 mongod 設定管理者帳密,上述可先在第一台伺服器設置(primary)

mongo mongsh1:27019
use admin
db.createUser( {
    user: "myUserAdmin",
    pwd: "",
    roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
  });
db.createUser( {
    user: "siteRootAdmin",
    pwd: "",
    roles: [ { role: "root", db: "admin" } ]
  });

也可以多新增一個admin帳號

db.createUser( {
    user: "admin",
    pwd: "",
    roles: [ { role: "root", db: "admin" } ]
  });

接著,透過以下命令建立一個 Key,並且複製到每一台機器 (mongsh1, mongsh2, mongsh3),之後每個 Mongod 實體會透過這把 Key 進行資料同步,接下來的動作比較複雜,順序不可以搞錯。很多人在這裡搞不定驗證功能,索性關閉驗證服務,這樣其實比較沒有保障,乖乖啟用驗證還是比較好的。

openssl rand -base64 741 > /home/mongod/mongodb-keyfile
chmod 600 /home/mongod/mongodb-keyfile
chown mongodb.mongodb /home/mongod/mongodb-keyfile

記得把這把 Key 放到每一台機器的 /home/mongodb-keyfile 檔案中。接下來我們就要啟用 Replica Set 與認證模式囉。再度編輯 /etc/mongod.conf 設定檔:

vim /etc/mongod.conf
security:
  keyFile: /var/lib/mongo/mongodb-keyfile
replication:
  replSetName: rs

在另外兩台伺服器可以修改設定檔為下

systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log
storage:
  dbPath: /home/mongod
  journal:
    enabled: true
processManagement:
  fork: true  
  pidFilePath: /var/run/mongodb/mongod.pid  # location of pidfile
net:
  port: 27019
  bindIp: 0.0.0.0  
security:
  keyFile: /home/mongod/mongodb-keyfile
replication:
 replSetName: bes

重新啟動 mongod 服務(另外兩台也要喔)

systemctl restart mongod

連線至剛剛的第一台 Mongod 並初始化 Replica Set,如下:

mongo mongsh1:27019
use admin
db.auth("siteRootAdmin", "");
rs.initiate()
rs.conf()

注意:正常完成時會有下面訊息出現:

接著新增另外兩台 Replica Set 節點,輸入以下命令:

rs.add("mongsh2:27019")
rs.add("mongsh3:27019")
rs.status()

注意:正常完成時會有下面訊息出現:

bes:PRIMARY> rs.status()
{
	"set" : "bes",
	"date" : ISODate("2017-09-09T14:51:02.381Z"),
	"myState" : 1,
	"term" : NumberLong(3),
	"heartbeatIntervalMillis" : NumberLong(2000),
	"optimes" : {
		"lastCommittedOpTime" : {
			"ts" : Timestamp(1504968659, 1),
			"t" : NumberLong(3)
		},
		"appliedOpTime" : {
			"ts" : Timestamp(1504968659, 1),
			"t" : NumberLong(3)
		},
		"durableOpTime" : {
			"ts" : Timestamp(1504968659, 1),
			"t" : NumberLong(3)
		}
	},
	"members" : [
		{
			"_id" : 0,
			"name" : "mongsh1:27019",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 4051,
			"optime" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDate" : ISODate("2017-09-09T14:50:59Z"),
			"electionTime" : Timestamp(1504964638, 1),
			"electionDate" : ISODate("2017-09-09T13:43:58Z"),
			"configVersion" : 67972,
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "mongsh2:27019",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 2961,
			"optime" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDate" : ISODate("2017-09-09T14:50:59Z"),
			"optimeDurableDate" : ISODate("2017-09-09T14:50:59Z"),
			"lastHeartbeat" : ISODate("2017-09-09T14:51:00.676Z"),
			"lastHeartbeatRecv" : ISODate("2017-09-09T14:51:01.607Z"),
			"pingMs" : NumberLong(0),
			"syncingTo" : "mongsh1:27019",
			"configVersion" : 67972
		},
		{
			"_id" : 2,
			"name" : "mongsh3:27019",
			"health" : 1,
			"state" : 2,
			"stateStr" : "SECONDARY",
			"uptime" : 2961,
			"optime" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDate" : ISODate("2017-09-09T14:50:59Z"),
			"optimeDurableDate" : ISODate("2017-09-09T14:50:59Z"),
			"lastHeartbeat" : ISODate("2017-09-09T14:51:00.676Z"),
			"lastHeartbeatRecv" : ISODate("2017-09-09T14:51:01.606Z"),
			"pingMs" : NumberLong(0),
			"syncingTo" : "mongsh1:27019",
			"configVersion" : 67972
		}
	],
	"ok" : 1
}
bes:PRIMARY> 

這樣就完成了,但如果出現有Statup誒
如果有伺服器出現:
“stateStr” : “STARTUP”,

例如:

bes:PRIMARY> rs.status()
{
	"set" : "bes",
	"date" : ISODate("2017-09-09T14:51:02.381Z"),
	"myState" : 1,
	"term" : NumberLong(3),
	"heartbeatIntervalMillis" : NumberLong(2000),
	"optimes" : {
		"lastCommittedOpTime" : {
			"ts" : Timestamp(1504968659, 1),
			"t" : NumberLong(3)
		},
		"appliedOpTime" : {
			"ts" : Timestamp(1504968659, 1),
			"t" : NumberLong(3)
		},
		"durableOpTime" : {
			"ts" : Timestamp(1504968659, 1),
			"t" : NumberLong(3)
		}
	},
	"members" : [
		{
			"_id" : 0,
			"name" : "mongsh1:27019",
			"health" : 1,
			"state" : 1,
			"stateStr" : "PRIMARY",
			"uptime" : 4051,
			"optime" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDate" : ISODate("2017-09-09T14:50:59Z"),
			"electionTime" : Timestamp(1504964638, 1),
			"electionDate" : ISODate("2017-09-09T13:43:58Z"),
			"configVersion" : 67972,
			"self" : true
		},
		{
			"_id" : 1,
			"name" : "mongsh2:27019",
			"health" : 1,
			"state" : 0,
			"stateStr" : "STARTUP",
			"uptime" : 2961,
			"optime" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDate" : ISODate("2017-09-09T14:50:59Z"),
			"optimeDurableDate" : ISODate("2017-09-09T14:50:59Z"),
			"lastHeartbeat" : ISODate("2017-09-09T14:51:00.676Z"),
			"lastHeartbeatRecv" : ISODate("2017-09-09T14:51:01.607Z"),
			"pingMs" : NumberLong(0),
			"syncingTo" : "mongsh1:27019",
			"configVersion" : 67972
		},
		{
			"_id" : 2,
			"name" : "mongsh3:27019",
			"health" : 1,
			"state" : 0,
			"stateStr" : "STARTUP",
			"uptime" : 2961,
			"optime" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDurable" : {
				"ts" : Timestamp(1504968659, 1),
				"t" : NumberLong(3)
			},
			"optimeDate" : ISODate("2017-09-09T14:50:59Z"),
			"optimeDurableDate" : ISODate("2017-09-09T14:50:59Z"),
			"lastHeartbeat" : ISODate("2017-09-09T14:51:00.676Z"),
			"lastHeartbeatRecv" : ISODate("2017-09-09T14:51:01.606Z"),
			"pingMs" : NumberLong(0),
			"syncingTo" : "mongsh1:27019",
			"configVersion" : 67972
		}
	],
	"ok" : 1
}
#mongo localhost:27019
bes:PRIMARY> (有時候出現是bes:SECONDARY>,都可以設置)
bes:PRIMARY>use admin
bes:PRIMARY>db.auth("siteRootAdmin","")
bes:PRIMARY>var cfg={_id:"bes",members:[{_id:0,host:"mongsh1:27019"},{_id:1,host:"mongsh2:27019"},{_id:2,host:"mongsh3:27019"}]}
bes:PRIMARY>rs.reconfig(cfg)
bes:PRIMARY>rs.status()

這樣就大功告成了!!!

 

Reference:

MongoDB Replica Set 高可用性架構搭建

mongodb 副本集搭建

Git 指令

注意事項

由 project/.git/config 可知: (若有更多, 亦可由此得知)

  • origin(remote) 是 Repository 的版本
  • master(branch) 是 local 端, 正在修改的版本

平常沒事不要去動到 origin, 如果動到, 可用 git reset –hard 回覆到沒修改的狀態.

Git 新增檔案

  • git add . # 將資料先暫存到 staging area, add 之後再新增的資料, 於此次 commit 不會含在裡面.
  • git add filename
  • git add modify-file # 修改過的檔案, 也要 add. (不然 commit 要加上 -a 的參數)
  • git add -u # 只加修改過的檔案, 新增的檔案不加入.
  • git add -i # 進入互動模式

Git 刪除檔案

  • git rm filename

Git 修改檔名、搬移目錄

  • git mv filename new-filename

Git status 看目前的狀態

  • git status # 看目前檔案的狀態

Git Commit

  • git commit
  • git commit -m ‘commit message’
  • git commit -a -m ‘commit -message’ # 將所有修改過得檔案都 commit, 但是 新增的檔案 還是得要先 add.
  • git commit -a -v # -v 可以看到檔案哪些內容有被更改, -a 把所有修改的檔案都 commit

Git 產生新的 branch

  • git branch # 列出目前有多少 branch
  • git branch new-branch # 產生新的 branch (名稱: new-branch), 若沒有特別指定, 會由目前所在的 branch / master 直接複製一份.
  • git branch new-branch master # 由 master 產生新的 branch(new-branch)
  • git branch new-branch v1 # 由 tag(v1) 產生新的 branch(new-branch)
  • git branch -d new-branch # 刪除 new-branch
  • git branch -D new-branch # 強制刪除 new-branch
  • git checkout -b new-branch test # 產生新的 branch, 並同時切換過去 new-branch
  • # 與 remote repository 有關
  • git branch -r # 列出所有 Repository branch
  • git branch -a # 列出所有 branch

Git checkout 切換 branch

  • git checkout branch-name # 切換到 branch-name
  • git checkout master # 切換到 master
  • git checkout -b new-branch master # 從 master 建立新的 new-branch, 並同時切換過去 new-branch
  • git checkout -b newbranch # 由現在的環境為基礎, 建立新的 branch
  • git checkout -b newbranch origin # 於 origin 的基礎, 建立新的 branch
  • git checkout filename # 還原檔案到 Repository 狀態
  • git checkout HEAD . # 將所有檔案都 checkout 出來(最後一次 commit 的版本), 注意, 若有修改的檔案都會被還原到上一版. (git checkout -f 亦可)
  • git checkout xxxx . # 將所有檔案都 checkout 出來(xxxx commit 的版本, xxxx 是 commit 的編號前四碼), 注意, 若有修改的檔案都會被還原到上一版.
  • git checkout — * # 恢復到上一次 Commit 的狀態(* 改成檔名, 就可以只恢復那個檔案)

Git diff

  • git diff master # 與 Master 有哪些資料不同
  • git diff –cached # 比較 staging area 跟本來的 Repository
  • git diff tag1 tag2 # tag1, 與 tag2 的 diff
  • git diff tag1:file1 tag2:file2 # tag1, 與 tag2 的 file1, file2 的 diff
  • git diff # 比較 目前位置 與 staging area
  • git diff –cached # 比較 staging area 與 Repository 差異
  • git diff HEAD # 比較目前位置 與 Repository 差別
  • git diff new-branch # 比較目前位置 與 branch(new-branch) 的差別
  • git diff –stat

Git Tag

  • git tag v1 ebff # log 是 commit ebff810c461ad1924fc422fd1d01db23d858773b 的內容, 設定簡短好記得 Tag: v1
  • git tag 中文 ebff # tag 也可以下中文, 任何文字都可以
  • git tag -d 中文 # 把 tag=中文 刪掉

Git log

  • git log # 將所有 log 秀出
  • git log –all # 秀出所有的 log (含 branch)
  • git log -p # 將所有 log 和修改過得檔案內容列出
  • git log -p filename # 將此檔案的 commit log 和 修改檔案內容差異部份列出
  • git log –name-only # 列出此次 log 有哪些檔案被修改
  • git log –stat –summary # 查每個版本間的更動檔案和行數
  • git log filename # 這個檔案的所有 log
  • git log directory # 這個目錄的所有 log
  • git log -S’foo()’ # log 裡面有 foo() 這字串的.
  • git log –no-merges # 不要秀出 merge 的 log
  • git log –since=”2 weeks ago” # 最後這 2週的 log
  • git log –pretty=oneline # 秀 log 的方式
  • git log –pretty=short # 秀 log 的方式
  • git log –pretty=format:’%h was %an, %ar, message: %s’
  • git log –pretty=format:’%h : %s’ –graph # 會有簡單的文字圖形化, 分支等.
  • git log –pretty=format:’%h : %s’ –topo-order –graph # 依照主分支排序
  • git log –pretty=format:’%h : %s’ –date-order –graph # 依照時間排序

Git show

  • git show ebff # 查 log 是 commit ebff810c461ad1924fc422fd1d01db23d858773b 的內容
  • git show v1 # 查 tag:v1 的修改內容
  • git show v1:test.txt # 查 tag:v1 的 test.txt 檔案修改內容
  • git show HEAD # 此版本修改的資料
  • git show HEAD^ # 前一版修改的資料
  • git show HEAD^^ # 前前一版修改的資料
  • git show HEAD~4 # 前前前前一版修改的資料

Git reset 還原

  • git reset –hard HEAD # 還原到最前面
  • git reset –hard HEAD~3
  • git reset –soft HEAD~3
  • git reset HEAD filename # 從 staging area 狀態回到 unstaging 或 untracked (檔案內容並不會改變)

Git grep

  • git grep “te” v1 # 查 v1 是否有 “te” 的字串
  • git grep “te” # 查現在版本是否有 “te” 的字串

Git stash 暫存

  • git stash # 丟進暫存區
  • git stash list # 列出所有暫存區的資料
  • git stash pop # 取出最新的一筆, 並移除.
  • git stash apply # 取出最新的一筆 stash 暫存資料. 但是 stash 資料不移除
  • git stash clear # 把 stash 都清掉

Git merge 合併

  • Straight merge 預設的合併模式,會有全部的被合併的 branch commits 記錄加上一個 merge-commit,看線圖會有兩條 Parents 線,並保留所有 commit log。
  • Squashed commit 壓縮成只有一個 merge-commit,不會有被合併的 log。SVN 的 merge 即是如此。
  • cherry-pick 只合併指定的 commit
  • rebase 變更 branch 的分支點:找到要合併的兩個 branch 的共同的祖先,然後先只用要被 merge 的 branch 來 commit 一遍,然後再用目前 branch 再 commit 上去。這方式僅適合還沒分享給別人的 local branch,因為等於砍掉重練 commit log。

指令操作

  • git merge <branch_name> # 合併另一個 branch,若沒有 conflict 衝突會直接 commit。若需要解決衝突則會再多一個 commit。
  • git merge –squash <branch_name> # 將另一個 branch 的 commit 合併為一筆,特別適合需要做實驗的 fixes bug 或 new feature,最後只留結果。合併完不會幫你先 commit。
  • git cherry-pick 321d76f # 只合併特定其中一個 commit。如果要合併多個,可以加上 -n 指令就不會先幫你 commit,這樣可以多 pick幾個要合併的 commit,最後再 git commit 即可。

Git blame

  • git blame filename # 關於此檔案的所有 commit 紀錄

Git 還原已被刪除的檔案

  • git ls-files -d # 查看已刪除的檔案
  • git ls-files -d | xargs git checkout — # 將已刪除的檔案還原

Git 維護

  • git gc # 整理前和整理後的差異, 可由: git count-objects 看到.
  • git gc –prune
  • git fsck –full

Git revert 資料還原

  • git revert HEAD # 回到前一次 commit 的狀態
  • git revert HEAD^ # 回到前前一次 commit 的狀態
  • git reset HEAD filename # 從 staging area 狀態回到 unstaging 或 untracked (檔案內容並不會改變)
  • git checkout filename # 從 unstaging 狀態回到最初 Repository 的檔案(檔案內容變回修改前)

Git Rollback 還原到上一版

  • git reset –soft HEAD^
  • 編輯 + git add filename
  • git commit -m ‘rollback’

以下與 遠端 Repository 相關

Git remote 維護遠端檔案

  • git remote
  • git remote add new-branch http://git.example.com.tw/project.git # 增加遠端 Repository 的 branch(origin -> project)
  • git remote show # 秀出現在有多少 Repository
  • git remote rm new-branch # 刪掉
  • git remote update # 更新所有 Repository branch
  • git branch -r # 列出所有 Repository branch

抓取 / 切換 Repository 的 branch

  • git fetch origin
  • git checkout –track -b reps-branch origin/reps-branch # 抓取 reps-branch, 並將此 branch 建立於 local 的 reps-branch

刪除 Repository 的 branch

  • git push origin :heads/reps-branch
  • git push origin –delete reps-branch

Git 學習筆記 (1):安裝、選項設定、在本地使用 Git 工具

《佛法即是科學,科學即是佛法;佛法是超科學的》

《佛法即是科學,科學即是佛法;佛法是超科學的》

 

普朗克量子常數——神秘的宇宙精靈
普朗克博士和近代科學家已經用科學證實了佛法的奧義,佛法是超科學的。

愛因斯坦的老師、量子理論之父——普朗克博士,1918年獲得諾貝爾物理學獎。他感嘆道:我對原子的研究最後的結論是——世界上根本沒有物質這個東西,物質是由快速振動的量子組成!

有形無形皆是不斷振動的能量,兩者的分別在於振動頻率不同,因而產生不同意識或形式的不同物質。振動頻率高的成為無形的物質,如人的思想、感覺和意識;振動頻率低的成為有形物質,如看得到的桌子、椅子、人體等等。
用「頂天立地」來形容人類的處境是最恰當不過了。

人同時存在於兩種不同的世界,頭上頂著高層次的靈性世界,腳下踏著物質化的實體世界,人既有肉體也是靈體。乍聽之下靈與肉是兩個截然不同的觀念,但靈性和肉體並非毫不相干,因為物質即能量,有形無形皆是不斷振動的能量,兩者的分別在於振動頻率不同,因而產生不同意識或形式的不同物質。

振動頻率高的成為無形的物質,如人的思想、感覺和意識;振動頻率低的成為有形物質,如看得到的桌子、椅子、人體等等。關於物質即能量(energy,也就是我們熟知的「氣」或是物理學上的「振動」),源自古埃及和希臘的「秘傳哲理」談到宇宙七個原理的「振動原理」(principle of vibration)就明白指出:「沒有任何東西是靜止的,一切都在動,一切都在振動。」

而東方聖賢,如佛陀,也在2600年前指出,宇宙間的所有事物,都是由振動組成。近代的科學也印證了能量和物質間的關係,最有名的就是愛因斯坦的E=mc2(E是能量,m是質量,c是光速)。

然而,由於人類受限於感官所能觸及的三維空間及線性的時間觀念,誤把實體的、有邊界的物質,與連續的、波動的能量場視為兩種不同的東西,前者以牛頓的古典動力學(classical dynamics)為代表,而後者以馬克斯威爾(James C. Maxwell)的古典電動力學(classical electrodynamics)為代表,兩者成為19世紀末古典物理學達到巔峰的兩大支柱。

可是,當科學家再往最微細的次原子領域探索,或向最廣闊的宇宙蒼穹深究時,卻發現在人類感官經驗所不及的境地,物質與能量的本質其實是合而為一的。20世紀初的量子力學及相對論,也徹底顛覆了古典物理機械式的時空觀。最著名的就是德國量子物理學家普朗克的E=hv(E是能量,h是一個量子常數,v是振動的頻率),當一個事物常數不變的情況下,振動頻率越高,它的能量越強。

大衛·霍金斯的「能量級別論」
我們之所以認為「物質和能量」或「肉體和靈體」截然不同,是因為我們人類有著二元(兩極)化思考模式。我們所知道的事物,幾乎都是來自知識和邏輯,而知識和邏輯形成了思想,思想就成為語言的基礎,這種模式使得人類變成二元化的產物,有著二元化的思考方式。因此,在人的世界裡有「善」就有「惡」,有「對」自然有「錯」,有「好」更是有「壞」,有「快樂」當然也有「痛苦」,一切皆有對立面。

美國著名的精神科醫師大衛·霍金斯(Dr. David R.Hawkins)的「能量級別論」研究告訴我們,善的能量級別高,惡的能量級別就低。如下表:
ADVERTISEMENT
1. 開悟正覺:700~1000
2. 安詳平和:600
3. 寧靜喜悅:540
4. 愛與崇敬:500
5. 理性明智:400
6. 寬容原諒:350
7. 希望樂觀:310
8. 淡定信賴:250
9. 勇氣肯定:200
10. 驕傲輕蔑:175
11. 憤怒仇恨:150
12. 渴望慾望:125
13. 恐懼焦慮:100
14. 憂傷懊悔: 75
15. 冷漠絕望: 50
16. 罪惡譴責: 30
17. 羞愧恥辱: 20
低於10的人,亞健康、慢性病或者病重
接近0級的人,頻臨死亡。

所以,古人云「生命在於運動」 ,這句話無論在「內靜外動(體育)」還是「外靜內動(禪定)」,都是正確的。
打個比方,物質和能量像是處於一漸層連續體(continuum)的兩極,一極為黑,一極為白,介於兩極之間是灰色,而這具有黑白兩極特色的灰色,包含著從偏白的灰色漸次發展到偏黑的灰色,這現象正如「秘傳哲理」中「兩極原理」(Principle of Polarity)所說的:「一切成雙,一切皆有兩極,一切皆有對立面,相似和相異是一樣的,相反的東西其本質也是一樣的,只是在程度上有所不同,極端的狀況會彼此相遇,所有真理不過是半真理,所有的矛盾也許互相調和。」。

因此,人的靈體和肉體是同一件事,同屬一漸層連續體的兩端,正如是與非、善與惡、快樂與痛苦本質並無不同,分別只在於能量振動有所差異。

如果以靈學和療愈學來說,能量振動頻率高而且精細的能量,是屬於高層次的自性本體;當振動頻率降低時,產生的物質就愈粗重(比如人的肉體),肉體在人類的四個次元中是頻率最低的。

為什麼人的肉眼看不見靈體?
也許有人要問,既然有靈體的存在,為什麼人的肉眼看不見,聽不到,摸不著? 一般而言,人類生存的世界是一個物質世界,位於前面所談的連續體的末端,和另一端無形靈性世界相較,這個物質世界比重大、振動低,因此肉體的察覺力非常有限。

人類經由眼、耳、鼻、舌、身來感覺。每一種感官,都可以察覺到高高低低不同的頻率。

例如人的耳朵可聽到的頻率範圍,最高可達到每秒20000赫茲、最低可聽到每秒16赫茲。人的眼睛,可以看到某一個範圍內的頻率,例如當振動頻率在500~536兆赫之間時,眼睛就會看到黃色。人的肉眼可以分辨紅橙黃綠藍靛紫,紫色是人類肉眼可以看到顏色的極限。其實,在紫色之上還有振動頻率更高的紫外線,在紅色之下也有振動頻率更低的紅外線,但因為振動頻率過高或過低,超過人類肉眼可以看到的範圍,所以我們看不見。電磁波頻譜從交流電的幾十赫茲到伽馬射線的大於3×1019赫茲,範圍非常之大,而人眼可見的光波只是其中很小很小的一段。

我們察覺不到的事物,難道就表示它不存在嗎?事實上它一直都存在,而且一直存在我們的四周。上面所談的紫外線或紅外線,它不但存在,而且還滲透到人類的肉體之中。在肉體或物質世界之外,存在著振動頻率更高的廣大世界。如果我們調整自己的能量振動頻率,就可以突破限制,接受到廣大世界中的信息,而不再只是限制在肉體或物質世界的層次中。

世上所有的東西,不論是固體、氣體或是液體,不論是有形或無形,都是一種能量的表現。而能量是不滅的,既不能被創造也無法被銷毀,這也是經過科學家如愛因斯坦等人所印證過的事實。

然而,科學家還印證了另一事實,那就是「能量是可以轉換的」,可以從振頻低的一極轉換成連續體上振頻高的另一極,這一事實對人類來說可是個大好消息,這表示我們是可以經由一些方法來調高我們自己的能量。也就是說,我們可以把粗糙笨重、密度大的能量,升華成精細輕快、密度小的能量。

正基於這個觀點;UFO專家提出大膽設想,以前認為在外星的ufo生物其實可能生活在地球上,只不過他們生活在高頻率空間中,我們的肉眼所見頻率是看不到這個空間的。

這讓我想起清華大學有門課程,關於「物質、能量、信息」,揭示了宇宙三種不同的存在形式。傳統養生學經常提到「人有三寶精、氣、神」,剛好對應了物質(精)、能量(氣)、信息(神)。這難道是巧合嗎?結合《道德經》延伸,物質(陽)、能量(?)、信息(陰)。「道生一、一生二、二生三、三生萬物,萬物負陰而抱陽,中炁以為和」。「一」是什麼?「炁」又是什麼?人的肉眼看得到信息嗎?看得到能量嗎?

共振能使低頻變高頻:
為了說明能量是如何從低振頻轉換到高振頻,必須提到1665年荷蘭科學家賀金斯(Christian Huygens)所發現的「共振原理」(entrainment):當兩種有著不同周期的物質能量相遇時,振動韻律強大的物質會使較弱的一方以同樣的速率振動,而形成同步共振現象。也就是說,強大韻律的振動投射到另一有相對應頻率的物體上,而此振動韻律弱的物體由於受到相對應頻率之周期性的刺激,因而與較強的物體產生共鳴而振動。

賀金斯曾在房間裡的牆上並排放置不同速率的老爺鐘,然後走出房間,第二天再回來時發現老爺鐘的鐘錘皆以同速率同步擺動,其後許多人相繼重複此鍾錘實驗,屢試不爽。事實上,「共振」可以說是一種共鳴現象,在我們日常生活中到處可見,比如琴弦,未振動的琴弦會受強烈振動琴弦的影響而一起共振;再舉個女高音震破玻璃杯的例子,女高音高頻的歌聲(無形)能提高玻璃杯(有形)的振動速率,當振動高到某一程度,玻璃杯無法再維持玻璃的形狀因而破碎。

當你和人談話很投機產生共鳴時,或課堂上老師的談話很吸引你而你猛點頭時,你的腦波可能正在共振;有時與人相處,彼此雖無言語卻靈犀相通,也是共振的現象。這也是為什麼許多人願意花錢買機票,千里迢迢去參加某法師或牧師主持的法會或布道大會,你若坐在他們的振頻範圍之內,你的能量也會隨之提高。

你可能會問,能量的「高」和「低」是怎麼定的?到底能量「高」或「低」意所何指?我們常聽人用「能量」來形容人、物或地理環境,「此人很有能量」或「這地方能量很強,風水不錯」。可惜的是,目前為止,科學界還沒有任何「絕對」的科學標準或儀器能精確測量世上所有的能量。

因此,在療愈學或靈學上,要測量能量的高或低,傳統上都是靠測量者的超感能力(超視覺、超聽覺、超嗅覺、超味覺、超觸覺或動覺)。由於每一種能量皆有特定的脈動(亦即其振動頻率),可以用超感官去測量,舉個用超觸覺或肌肉動覺測能量的例子:如到市場買水果,我伸手去感覺來自兩個不同農場的蘋果,A蘋果感覺上脈動慢些,B蘋果感覺上脈動快些、振動的「質」也精細些,我當然會選擇能量較「高」的B蘋果。

除了靠超感能力外,各文化也有特定的方法測量能量,如西方用占卜杖或占卜枝來測地下水或礦脈,這古老的方法即使是在科學發達的今天仍被廣泛使用。安慈的大哥10多年前退休後想離世獨居,在加州的天使營山區買下20多英畝的地,這大片荒地當時沒路、沒電、沒水,要在其上建屋子居住,當務之急自然是找水源鑿井,他請的便是當地的「導者」(Dowser)為他找水。安慈的養父生前在加州的莫得斯朵(Modesto)擁有大片農場,農場上10多幢房子是安慈小時候跟著他合建的,他告訴我,他找水源從不假他人,也是用柳枝占卜找水源。本書在「氣輪」一章所談的擺錘測量也是相同的原理。

近代一位法國物理學家寶維斯(Antoine Bovis)用鍾錘原理髮展出「寶維斯尺度」(Bovis Scale),有系統地用數據來測量並記錄物質的能量,任何東西都可測量出用數字代表的值。對生物體來說,6500單位以下是負值,對健康有害;6500為中性,不好不壞,若是對健康有益,必須至少在8000以上。比如說,如果將之用來測量地理,所得之值若是低於6500則不適合人居住,可能是地下水脈流經之處或正好是地球輻射線較強之處。另外,教堂鐘聲為11000,宗教廟宇為14000。

若用「寶維斯尺度」來測量人體,在細胞層次上,癌細胞都低於6500,正常細胞的DNA 高於6500,至於全身的能量,有病的人測出的數字低於6500,感覺疲倦的正常人為6500,身體健康的人為7500,精力充沛的人為8500,有能力療愈別人的人至少是8500,有靈媒能力之人少9000,不少長期修行者所測出的能量值遠超過10000。

療愈密碼,把低頻能量提升成高頻能量:
所謂的「療愈」,其實就是透過「共振」來轉換人的電磁場中低頻能量狀態,這表示我們是可以經由一些方法來調高我們自己的能量,把粗糙笨重、密度大的能量,轉化升華成精細輕快、密度小、振頻高的能量。共振可應用在人體的各個層次上,在細胞層次上來說,我們可以將人體內堆積過多的自由基轉換成為陰離子;在肉體上,可以將高度濃縮的腫瘤轉換成密度較小的健康肌肉;在情緒上,我們可以將比重大的痛苦升華成比重小的快樂;在認知上,可以將負面的批判轉換成正面的欣賞,將悲觀的看法轉為樂觀的態度;在靈性上,可以將人的意識從原本只認同有形的肉體,提高到也能感覺無形靈體的狀態,從而喚醒我們的靈性意識,重新和自性本體聯結,最後達到和宇宙合為一體的狀態。

我們從物理學的角度出發,卻準備帶各位走一趟心靈之旅,心物本來就是相互融合的,我們發現許多西方近代偉大的心靈,越深入其物質科學研究領域,就越能體會心靈與物質的相通之處。例如從玻姆的全息宇宙觀中,我們依稀可以看到一多相融溶的「華嚴世界」——整體包含個體,而個體也包含整體的訊息,每一個體都是本自俱足的。

在接下來的章節,我們會從「自性本體」、「高層自我」逐步認識到「低層自我」,在生命藍圖的暗示下,我們會體會到所謂「療愈」,其實就是回歸自性本體的「覺悟」過程,這過程始於「創傷」、終於療愈,卻從不曾離開創傷,以較時尚的科學術語來說,就是創傷本來就具有療愈的所有密碼,只等著我們去解碼,創傷與療愈本來就是同個本質的兩個面向,看似二元對峙,實則本自如一。就像華嚴世界一般,從高層自我到低層自我,從物質的肉身到高次元的能量體,所有的空間都是互相融合、互相滲透,自性本體從未遠離。請讀者不要把高層與低層看做一個直線的兩極,否則就墮入了二元化的思考模式,使得創傷與療愈反而變成互相否定對峙的客體。

依循本章所提的許多偉大學者從物質過渡到心靈的足跡,我們建議讀者在往下的身心探險旅程中,帶著三個寶貴的心靈鑰匙:

開放的視野:驚奇的喜悅往往隱藏在別無去路的困頓之後,所以別忙著否定任何與我們刻板經驗不同之處。跨越二元對立的平等心:莫要去區分好壞、善惡、高低,只要區分就有界限,就砌了一道阻礙悟道的高牆。

用心去體會的直覺:
碰到難解迷惑之處,與其用腦思考,不如用心去導航。

量子之父問道古聖先賢
看下圖:物質的分子結構
當有人問你,哪位是世界上最偉大科學家?你會肯定的回答:愛因斯坦!

愛因斯最偉大的成就:《相對論》1905年獲得諾貝爾物理學獎。其核心內容源於愛因斯坦兩個偉大的實驗:一個尺縮效應;一個鐘慢效應。

尺縮效應:
尺子的長度在三維空間相對不變,而在超越三維空間的速度下運行,速度越快尺子會越縮短。當速度越接近光速,尺子的質量接近於0(佛家稱為「空」),揭示宇宙中空間的相對性。

鍾曼效應:
鐘錶的時間在三維空間相對不變,而在超越三維空間的速度下運行,速度越快鐘錶會走得越慢。當速度越接近光速,鐘錶的時間趨於停止(佛家稱為「定」)。揭示宇宙中時間的相對性。

不可思議,是因為思維模式沒有超越三維空間的世界觀,但是,愛因斯坦和釋迦牟尼佛做到了!

再看看科學家在顯微鏡發現了什麼吧!
「物質-分子-原子-原子核-質子中子電子-納米-夸克……」

最終發現的物質,竟然在顯微鏡下是看不到的,這種物質被稱為「夸克」——世界上最小的物質或者類物質,或者根本不存在,不對!「有」或者「無」,陰和陽,色或空,乾脆叫「0」?

《道德經》「有,萬物之母,無,天地之始」。「萬物負陰而抱陽,中炁以為和」。

《金剛經》「一切有為法,如夢幻泡影,亦露亦如電,應作如是觀」。

《心經》「色不異空,空不異色,色即是空,空即是色,受想行識,亦復如是」。

正像科學家發現的「夸克」,這種物質既簡單又神秘——超級震撼了人類!

談到夸克的特性,更是奇妙無比:

1、其中有兩種夸克——中微子和光子,在絕對靜止狀態下,它質量是0,它一動要麼是+、要麼是-,所以,科學家發現的「夸克」幾乎同時出現一正一負的「對夸克」。這不禁讓我想起老子《道德經》「道生一、一生二、二生三、三生萬物」,其中二是指陰陽,三應該是五行(因為元素周期表裡面的元素幾乎都可以按「金木水火土」分類了),「三生萬物」可以理解為這五種基本元素按不同比例的組合就形成了宇宙萬物啊!那麼「一」是什麼呢?沒錯,當然就是指「0」!還記得佛祖說過「四大皆空」嗎?還記得六組說「本來無一物」嗎?

2、它的壽命 ∞(無窮大)。難怪古聖先賢、歷朝歷代的修行者都在「禪」「定」修煉悟道,以求長生久世,其實是都想得到這個∞(無量壽),因為「一定成功」!不「定」當然就難成功!順便提一下:質量為0的東東正是無量光!「無量光」「無量壽」合起來正是佛家唱號「阿彌陀佛」,道家稱的「無量壽佛」,這些咒語神秘莫測,世間幾個人能明白啊!0其小無內其大無外,表示「空間」;∞不生不滅無始無終,表示「時間」;空間為「宇」,時間為「宙」,怪不得古往今來那些修道者果真很長壽啊!我恍然大悟——原來古聖先賢(內求法)和現代科學家(外求法)都是在忙活探求「宇宙」真相呢。

讓我們把思維進一步擴展一下,如果人體是一個小宇宙的話,那裡面的粒子是不是就相當於宇宙當中的星球啊,一定是的,那粒子上面會不會有生命呢?可能就有生命存在。這可不是我思路廣,釋迦牟尼有一個三千大千世界學說。

「釋迦牟尼佛在2500年前就對三千大千世界了如指掌,在欲界、色界、無色界三界中有三十三個界定範圍,而生命則以十種不同的形式和等級遍及於三界,乃至三千大千世界中,在華藏世界內有十種不可說佛剎微塵香水海,無極無盡。有無數個像西方極樂世界的星體,並且仔細詳盡地解說那裡的情況。

他告訴人們地球就像一個橢圓形的庵摩羅果,這是2000多年以後才被科學家證實的啊!他講我們的身體就是由這若干極微緣聚構成,他還講了一粒沙里還有這樣的三千大千世界。一粒沙子就像一個宇宙一樣,裡面也含藏像我們這樣的智慧生命,有星球,也有山川河流。他還說一滴水中有八萬四千生命 ……」

如果人類未發現顯微鏡,恐怕到現在還認為佛陀是在講迷信了!聽起來很玄哪!可是如果看看這些照片,我覺得這也並不玄,一切皆有可能。所有的科學定律都只能在特定的時空中成立,它們多數從一開始就註定會遭到修正甚至否定的命運。釋迦牟尼佛觀察宇宙就像一個視力正常的人觀察大象一樣,而科學的方法則是一群盲人在摸象,他們研究的成果絕不是大象的全體和真實。

佛陀教我們要「但求本,不愁末」。他說法四十九年,種種方便,長說短說、橫說豎說,並非是想告訴我們大象鼻子有多長,尾巴多少毛這類技術的問題,而是教我們這群盲人睜開眼睛而已!

如此看來,我們的肉眼真的很局限,讓我們只看到表象,看到假象,而看不到真相。我們的「看不見就不相信」的觀念是不在理,得轉變一下了!!!

現代物理科學研究者也應知,要找到組成物質的最細結構(如量子級別物質),只能是徒費心機,或者「如是說」而已,因物質只是一種幻相,它沒有常而有質礙的最細塵粒,若在虛幻的現象界中尋找,將會離真相越來越遠,永遠也不可能窮盡其微,只有轉而研究人的內心(如禪定態),宇宙物質之迷才有解開之時。