數(shù)據(jù)庫與緩存是服務端開發(fā)人員的必學知識點.
"數(shù)據(jù)庫"是一種信息記錄、存取的虛擬標記地點的集合統(tǒng)稱. 比如現(xiàn)實生活中, 我們經(jīng)常會用到文件柜、書桌等等數(shù)據(jù)存取容器.
在對容器進行數(shù)據(jù)存取的時候, 我們會為每一層打上一個標簽表示一種分類項. 而這種在數(shù)據(jù)庫
中劃分子分類形成了表
的概念. 這就是我們通常所說的結構化數(shù)據(jù)庫
.
由于通常數(shù)據(jù)表之間可能會存在依賴關系, 某一(或者多)層通常可能會用于同一種用途. 這種用途將一層劃分為索引表, 二層劃分為分類表, 三層劃分為數(shù)據(jù)表.
實現(xiàn)這種功能與依賴關系的數(shù)據(jù)庫, 我們稱之為: 關系型數(shù)據(jù)庫
. 它可以定義一套規(guī)范并且建立數(shù)據(jù)存取模型, 這樣方便維護一整套結構化的數(shù)據(jù)信息.
每當我們需要對數(shù)據(jù)進行結構化操作(查詢、增加、刪除、修改)的時候, 需要在計算機中用一種通俗易懂的語言表達方式
來進行助記. 這種結構化查詢語言稱之為SQL
.
我們通常將數(shù)據(jù)存儲完畢后, 能通過指定或特定的一(多)種方式對數(shù)據(jù)進行操作. 在項目開發(fā)的初期, 這并沒有太大的問題.
但是隨著數(shù)據(jù)量的不斷增大, 在數(shù)據(jù)庫的內(nèi)存中已經(jīng)放不下這么多數(shù)據(jù). 我們的數(shù)據(jù)逐漸無法被加載到內(nèi)存中: 只會在使用的時候才會進行(隨機)讀取. 而這會加大磁盤I/O.
我們知道通常磁盤的讀寫速度基本上會比內(nèi)存讀寫慢幾個數(shù)量級(即使是SSD), 大量請求可能瞬間將磁盤IO占滿并出現(xiàn)數(shù)據(jù)庫的CPU利用率低、內(nèi)存頻繁進行修改/置換等問題.
為了解決這些問題, 出現(xiàn)了很多解決方案: 讀、寫分離、分表分庫等等. 雖然有了這些方案, 但是也同樣回引來新的問題: 主從同步、分布式事務等問題.
"緩存"則是近十年興起的概念, 它的本質是一份數(shù)據(jù)結構化存儲在內(nèi)存中的副本. 高級的緩存
我們也可以將其稱之為內(nèi)存數(shù)據(jù)庫
或NOSQL
(非關系型)數(shù)據(jù)庫.
"緩存"也是一種"另類"解決數(shù)據(jù)庫問題點一種手段! 它通過豐富的數(shù)據(jù)結構擴展了數(shù)據(jù)模型的組合能力, 通過簡單的使用方法與高效的連接方式提供更好數(shù)據(jù)操作方式.
"緩存"將查詢、更新較為頻繁的熱
數(shù)據(jù)組成一個集合加載進內(nèi)存中, 較少使用的冷
數(shù)據(jù)序列化到磁盤內(nèi)部. 高效利用內(nèi)存的同時, 根據(jù)變化的情況合理更新、刪除緩存.
這樣的方式配合數(shù)據(jù)庫都讀、寫分離與數(shù)據(jù)分區(qū)將數(shù)據(jù)合理的從一個數(shù)據(jù)集副本分散到多個數(shù)據(jù)集副本, 有效的減少性能問題點產(chǎn)生并且提升了整個業(yè)務系統(tǒng)的橫向擴展能.
DB庫是cf框架封裝自MySQL 4.1協(xié)議實現(xiàn)的客戶端連接庫, 提供MySQL斷線重連、SQL重試、連接池等高級特性.
Cache庫是cf封裝自Redis 2.0協(xié)議實現(xiàn)的客戶端連接庫, 提供Redis斷線重連、命令重試、連接池等高級特性.
在使用下面的API之前, 請先確保已經(jīng)導入庫: local DB = require "DB"
.
opts表的參數(shù)決定如何連接到MySQL, 表屬性如下:
host - MySQL主機名或IP地址(string類型).
port - MySQL端口號(int類型).
charset - MySQL字符集設置.
database - MySQL庫的名稱.
username - MySQL用戶賬戶(string類型).
password - MySQL用戶密碼(string類型).
max - MySQL的最大連接池大小(int類型).
這個方法返回一個新創(chuàng)建db對象
開始連接MySQL. 連接成功返回True, 否則將會持續(xù)進行連接并且輸出連接失敗原因的日志.
數(shù)據(jù)庫查詢語句調用方法, SQL為string類型的的一個標準SQL語句.
返回值為ret與err. 查詢成功ret為一個結果集數(shù)組, 在發(fā)生錯誤時未nil, err為錯誤信息.
在使用下面的API之前, 請先確保已經(jīng)導入庫: local Cache = require "Cache"
.
opts表的參數(shù)決定如何連接到MySQL, 表屬性如下:
host - Redis主機名或IP地址(string類型).
port - Redis主機端口號(int類型).
auth - Redis主機設置的密碼, 默認為:nil.
db - Redis的數(shù)據(jù)庫設置.
max = 最大連接池大小(int類型).
此方法返回一個新創(chuàng)建的Cache對象.
開始連接Redis. 連接成功返回True, 否則將會持續(xù)進行連接并且輸出連接失敗原因的日志.
Cache支持大部分的redis API, 目前測試過多API在script/test_Cache.lua
文件內(nèi)部都有展示.
DB庫的操作與使用流程非常簡單, 其目標是簡化開發(fā)人員在業(yè)務編寫過程中的使用難點.
啟動一個MySQL實例并且初始化完畢, 具體安裝與初始化方法根據(jù)平臺不同而不同, 這不再本文講解范圍內(nèi).
然后我們使用默認的root
用戶并且root
賬戶、密碼設置完畢. 這里為了演示方便, 我們將root
密碼設置為: 123456789
.
創(chuàng)建一個叫cf_mall
的數(shù)據(jù)庫字符集編碼都設為utf-8
. 并且在cf_mall
數(shù)據(jù)庫中創(chuàng)建一個叫做cf_users
的表, 如下所示:
# 創(chuàng)建`cf_mall`數(shù)據(jù)庫
CREATE DATABASE IF NOT EXISTS `cf_mall` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
# 創(chuàng)建`cf_users`用戶表
CREATE TABLE IF NOT EXISTS `cf_mall`.`cf_users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '用戶ID',
`age` tinyint(3) unsigned NOT NULL COMMENT '用戶年齡',
`name` varchar(255) NOT NULL COMMENT '用戶名',
`username` varchar(255) NOT NULL COMMENT '用戶賬戶',
`password` varchar(255) NOT NULL COMMENT '用戶密碼',
`email` varchar(255) NOT NULL DEFAULT '' COMMENT '用戶郵箱',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
以上數(shù)據(jù)庫創(chuàng)建語句可以在一些MySQL GUI工具中直接運行.
現(xiàn)在, 讓我們利用上面學到的API嘗試將作者的信息寫入進去. 同時為了避免密碼原文顯示, 我們需要使用crypt庫的base64方法將密碼進行編碼.
local crypt = require "crypt"
local DB = require "DB"
local db = DB:new {
host = "localhost",
port = 3306,
username = 'root',
password = 123456789,
database = "cf_mall",
charset = "utf8"
}
db:connect()
db:query(string.format([[
INSERT INTO `cf_mall`.`cf_users`
(`name`, `age`, `username`, `password`, `email`)
VALUE
('%s', '%s', '%s', '%s', '%s')
]],
'水果糖的小鋪子', '29', 'candymi', crypt.base64encode('123456789'), '869646063@qq.com')
)
local ret, err = db:query("SELECT * FROM `cf_mall`.`cf_users` WHERE `name` = '水果糖的小鋪子'")
if not ret then
return print(ret, err)
end
return print('name:', ret[1].name, 'password:', ret[1].password, 'email:', ret[1].email)
最后我們檢查數(shù)據(jù)庫內(nèi)是否已經(jīng)寫入了我們需要存儲的數(shù)據(jù). 如果使用的SQL有語法錯誤導致寫入失敗, 請使用print
檢查db:query
操作否出現(xiàn)錯誤.
同時我們在console控制臺上可以檢查是否輸出了我們剛才寫入到cf_users
的信息.
Cache庫擁有非常簡單的使用方法, 幾乎能運行所有Redis已提供的命令. 并且協(xié)議是二進制安全的(binary safe).
啟動并運行一個redis實例. 具體安裝與運行方法根據(jù)平臺不同而不同, 這不再本文講解范圍內(nèi).
并且這里為了演示示例簡單, 我們將不設置任何auth
并且使用默認的db
.
我們將列出目前已知的一些知名大眾化語言, 然后將其寫入到Redis中.
local Cache = require "Cache"
local cache = Cache:new {
host = 'localhost',
port = 6379,
}
cache:connect()
local ok, msg = cache:rpush("languages", "C", "C++", "Java", "Golang", "Ruby", "Python", "PHP", "Lua")
if not ok then
return print(ok, msg)
end
print("當前l(fā)anguage的總數(shù)為:", msg)
最后, 讓我們用Redis自帶的命令行工具查看是否真實寫入了數(shù)據(jù).
[candy@MacBookPro:~] $ redis-cli
127.0.0.1:6379> lrange languages 0 -1
1) "C"
2) "C++"
3) "Java"
4) "Golang"
5) "Ruby"
6) "Python"
7) "PHP"
8) "Lua"
127.0.0.1:6379>
可以看到數(shù)據(jù)已經(jīng)寫入進去. 如果發(fā)送參數(shù)錯誤與語法發(fā)生錯誤, msg將會是您排查錯誤的有效信息.
更多API詳情請參考MySQL、Redis的使用文檔并且在實際開發(fā)中進行體驗.
下一章節(jié)我們將繼續(xù)學習如何利用httpc庫請求第三方接口
更多建議: