一.redis:非關(guān)系型數(shù)據(jù)庫(kù),kv存儲(chǔ)系統(tǒng)(REmote Dictinoary server)
提高高速緩存服務(wù) -- 緩存熱點(diǎn)數(shù)據(jù)(訪問(wèn)量大察郁,數(shù)據(jù)量不大)衍慎,緩解了數(shù)據(jù)庫(kù)的壓力(高頻訪問(wèn)數(shù)據(jù)不用直接訪問(wèn)數(shù)據(jù)庫(kù))
a.在linux服務(wù)器安裝redis:
在linux系統(tǒng)中輸入以下命令:
在官網(wǎng)下載redis的安裝包
wget http://download.redis.io/releases/redis-5.0.3.tar.gz
解壓文件
gunzip redis-5.0.0.tat.gz
解歸檔文件
tar -xvf redis-5.0.3.tar
進(jìn)入redis文件
cd redis-5.0.3
查看是否安裝有g(shù)un編譯器套件
gcc --version
編譯并且安裝
make && make install
b.redis基本操作:
redis的客戶(hù)端、服務(wù)器和哨兵等快捷方式默認(rèn)放在/usr/local/bin文件夾下
redis提供了兩種數(shù)據(jù)持久化的方案:
1.RDB -- 默認(rèn)開(kāi)啟
2.AOF -- (每?jī)擅氡4嬉淮危?-默認(rèn)關(guān)閉狀態(tài)--appendonly yes (打開(kāi)AOF)
redis-benchmark -a 密碼:查看服務(wù)器每秒鐘能剛處理多好個(gè)redis命令
redis-server --requirepass 123123 --appendonly yes > redis.log 2> redis-error.log & :啟動(dòng)redis服務(wù)器皮钠,密碼設(shè)為123123稳捆,啟動(dòng)后加載文檔放在redis.log,錯(cuò)誤信息文檔放在error.log, &符號(hào)表示啟動(dòng)后自動(dòng)在后臺(tái)運(yùn)行
redis-cli : 啟動(dòng)redis客戶(hù)端并且連接自己
redis-cli -h ip地址 -p 端口號(hào):連接服務(wù)器
auth 密碼 : 驗(yàn)證身份
ping -- 心跳事件(檢查是否臉上服務(wù)器)
set -- 設(shè)置鍵值對(duì)
get -- 獲取值
expire -- 設(shè)置超時(shí)時(shí)間
del -- 刪除鍵
keys -- 查看鍵
exists -- 判斷鍵是否存在
flushdb -- 清除當(dāng)前數(shù)據(jù)庫(kù)中的鍵值對(duì)
flushall -- 清除所有數(shù)據(jù)庫(kù)中的所有鍵值對(duì)
dbsize 數(shù)據(jù)庫(kù)編號(hào)-- 查看當(dāng)前數(shù)據(jù)庫(kù)的存儲(chǔ)鍵值對(duì)的個(gè)數(shù)
select 數(shù)據(jù)庫(kù)編號(hào)-- 切換至指定的數(shù)據(jù)庫(kù)
shutdown -- 關(guān)閉數(shù)據(jù)庫(kù)服務(wù)器
save -- 保存數(shù)據(jù)
bgsave -- 后臺(tái)去保存數(shù)據(jù)(不會(huì)占用當(dāng)前線程,影響當(dāng)前控制臺(tái))
二.redis五中常用value類(lèi)型:
a.字符串--String:value值類(lèi)型是字符串
append myphone 'nookia' : 如果myphone已經(jīng)存在數(shù)據(jù)庫(kù)中麦轰,就把值添加在那個(gè)值后面乔夯,不存在就創(chuàng)建并賦值
incr tt: 如果tt存在,將它的值加1款侵,如果不存在就創(chuàng)建末荐,值為1
incrby num 100 : 如果num是int類(lèi)型,就給它的值加100新锈,不是就報(bào)錯(cuò)
decr
decrby
incrbyfloat key 0.1 : 增加浮點(diǎn)數(shù)(小數(shù))
getrange key 0 8 :獲取key的值中下標(biāo)0到8的值
set
mset
mget
get
getset key value:將key的值改為value甲脏,返回出舊值
b.哈希表--Hash:value值類(lèi)型是對(duì)象(字典)
hset dict1 key1 value1 key2 value2 : 在redis數(shù)據(jù)庫(kù)中存儲(chǔ)dict={'key1':'value1','key2':'value2'}
域存在
redis> hset dict1 key1 value1 key2 value2
(integer) 1
redis> hget dict1 key1
"value1"
域不存在
redis> hget dict1 mysql
(nil)
hset
hget
hkeys
hvals
hmset
hmget
hexists
hincrby
hincrbyfloat
c.列表--list
lpush list1 100 200 300 400 : 從左邊依次放入元素:list1=[400,300,200,100]
rpush list2 100 200 300 400 : 從右邊依次放入元素:list2=[100,200,300,400]
lrange list1 0 3 : 獲取list1下標(biāo)從0到3的元素
rpop list1: 從右邊取list1元素
lpop : 從左邊取元素
brpop list1 60 : list1中有元素直接獲取,60s內(nèi)還是沒(méi)有妹笆,就返回空
blpop
lindex list1 3 : 取出list1中下標(biāo)為3的元素
redis的list類(lèi)型可以實(shí)現(xiàn)兩種經(jīng)典的數(shù)據(jù)存儲(chǔ)結(jié)構(gòu):
棧(stack) -- FILO -- 先進(jìn)后出 -- lpush +lpop / rpush + rpop
隊(duì)列(queue) -- FIFO -- 先進(jìn)先出 -- lpush +rpop / rpush + lpop
函數(shù)直接或者間接的調(diào)用自己:函數(shù)的遞歸調(diào)用 (底層用到了棧結(jié)構(gòu))
d.集合--set
sadd set1 100 : 將100添加到set1中
smembers set1 : 查看set1中所有元素
sinter set1 set2 : 求set1和set2的交集
sunion set1 set2 : 求set1和set2的并集
sdiff set1 set2 : 求set1和set2的差集
srem set1 100 : 去除集合中的100
sismember set1 100 : 判斷集合中是否存在100
scard set1 : 查看集合中有多少個(gè)元素
spop set1: 移出并返回集合set1中的一個(gè)隨機(jī)元素
srandmember set1: 獲取set1中一個(gè)隨機(jī)元素块请,但不移出該元素
smove set1 set2 value : 將value從set1中移動(dòng)到set2中
e有序集合:sortedset
zadd / zcard / zcount / zincrby / zrange / zrem / zscore
三.主從復(fù)制,讀寫(xiě)分離(master -- salve)
一臺(tái)服務(wù)器做master晾浴,可以讀寫(xiě)修改等所有操作负乡;一臺(tái)服務(wù)器做slave,只能訪問(wèn)master數(shù)據(jù)庫(kù)脊凰,讀取數(shù)據(jù)
redis緩存數(shù)據(jù)抖棘,mysql保存數(shù)據(jù),
用mysql建表(聯(lián)動(dòng)型數(shù)據(jù))
"""
序列化 - 把對(duì)象轉(zhuǎn)換成字符或字節(jié)序列 - 串行化/腌咸菜
反序列化 - 把字符或者字節(jié)序列還原成對(duì)象 - 反串行化
Python中要實(shí)現(xiàn)對(duì)象的序列化和反序列有3種方案:
- json - load / loads / dump / dumps - 字符序列
- pickle - load / loads / dump / dumps - 字節(jié)序列
"""
import pickle
import time
import pymysql
import redis
class District(object):
"""行政區(qū)域"""
def __init__(self, distid, name):
self.distid = distid
self.name = name
def __str__(self):
return self.name
def __repr__(self):
return self.name
def main():
begin = time.time()
cli = redis.StrictRedis(host='120.78.202.21',
port=6379,
password='123123')
# 優(yōu)先從緩存中讀取數(shù)據(jù) 如果緩存沒(méi)有命中 才連接數(shù)據(jù)庫(kù)進(jìn)行查詢(xún)
if cli.exists('provinces'):
# 直接從緩存中通過(guò)鍵獲取數(shù)據(jù)并反序列化成Python中的對(duì)象
provinces = pickle.loads(cli.get('provinces'))
else:
provinces = []
con = pymysql.connect(host='120.78.202.21', port=3306,
database='hrs', charset='utf8',
user='root', password='123456')
try:
with con.cursor() as cursor:
# 查詢(xún)省級(jí)行政區(qū)域
cursor.execute(
'select `distid`, `name` from `tb_district` where `pid` is null')
# 將查詢(xún)結(jié)果放入列表容器
for dist_tuple in cursor.fetchall():
dist = District(*dist_tuple)
provinces.append(dist)
# 將列表序列化(pickle)然后放入Redis中緩存
cli.set('provinces', pickle.dumps(provinces))
finally:
con.close()
end = time.time()
print(f'執(zhí)行時(shí)間: {end - begin}秒')
print(provinces)
if __name__ == '__main__':
main()
互億無(wú)線發(fā)送短信代碼:
import io
import json
import logging
import random
from http.client import HTTPConnection
from urllib.error import URLError
from urllib.parse import urlencode
from redis import StrictRedis
def gen_code(length=8):
result = io.StringIO()
for _ in range(length):
result.write(str(random.randint(0, 9)))
return result.getvalue()
SMS_SERVER = '106.ihuyi.com'
SMS_URL = '/webservice/sms.php?method=Submit'
SMS_ACCOUNT = 'C10419651'
SMS_PASSWORD = 'a3ecaed032868ea37e612082566cc6ac'
MSG_TEMPLATE = '您的驗(yàn)證碼是:%s狸涌。請(qǐng)不要把驗(yàn)證碼泄露給其他人切省。'
def send_short_message(tel, code):
"""發(fā)送短信驗(yàn)證碼(互億無(wú)線)"""
params = urlencode({
'account': SMS_ACCOUNT,
'password': SMS_PASSWORD,
'content': MSG_TEMPLATE % code,
'mobile': tel,
'format': 'json'
})
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'text/plain'
}
conn = HTTPConnection(SMS_SERVER, port=80, timeout=10)
try:
conn.request('POST', SMS_URL, params, headers)
json_str = conn.getresponse().read().decode('utf-8')
return json.loads(json_str)
except URLError or KeyError as e:
logging.error(e)
return json.dumps({
'code': 500,
'msg': '短信服務(wù)暫時(shí)無(wú)法使用'
})
finally:
conn.close()
def main():
tel = input('請(qǐng)輸入手機(jī)號(hào):')
cli = StrictRedis(host='120.78.202.21',
port=6379,
password='123123')
mass = gen_code()
if not cli.exists(tel):
result = send_short_message(tel, mass)
print(result)
if result['code'] == 2:
print(result)
cli.set(tel, 1, ex=3600)
elif int(cli.get(tel)) < 3:
result = send_short_message(tel, mass)
if result['code'] == 2:
print(result)
cli.set(tel, 1, ex=3600)
cli.incr(tel)
else:
print('請(qǐng)不要一直發(fā),一小時(shí)三次帕胆,oj8k?')
if __name__ == '__main__':
main()
做短信業(yè)務(wù)的平臺(tái):
又拍云朝捆、luosimao、云片短信懒豹、SendCloud芙盘、互億無(wú)線