mysql和redis的區(qū)別
mysql是關(guān)系型數(shù)據(jù)庫,主要用于存放持久化數(shù)據(jù),將數(shù)據(jù)存儲在硬盤中,讀取速度較慢。
redis是非關(guān)系型數(shù)據(jù)庫,即將數(shù)據(jù)存儲在緩存中,緩存的讀取速度快,能夠大大的提高運行效率,但是保存時間有限
django中使用mysql的方法
通過繼承models.Model來生成數(shù)據(jù)庫表,詳情見Django模型的使用。
django中使用redis的方法
首先安裝python庫
pip3 install django-redis
在settings.py中增加如下代碼
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379',
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {"max_connections": 100}
},
},
}
REDIS_TIMEOUT=7*24*60*60
CUBES_REDIS_TIMEOUT=60*60
NEVER_REDIS_TIMEOUT=365*24*60*60
在業(yè)務(wù)邏輯代碼中加入
from django.core.cache import cache
此后,就可以通過
cache.set(key,value)
進行鍵值對的存儲。通過
cache.get(key)
進行鍵值對的查詢。
問題實例
在筆者實現(xiàn)的彈幕系統(tǒng)中,每一個發(fā)送到服務(wù)器的彈幕都要判斷其所對應(yīng)的活動是否接受圖片彈幕。是否接受圖片彈幕,原先存儲在mysql的活動表中。但是每次發(fā)送彈幕都要從mysql中查詢一次其所屬的活動會降低系統(tǒng)的性能,同時總活動數(shù)(相對于彈幕數(shù)量)較少,適合將其存到redis中。
由于mysql和redis中都會維護活動的相關(guān)信息,因此在增刪改查時需要保證數(shù)據(jù)的一致性。
考慮到請求的種類特點,此處采用了一種較為簡潔的策略:
- 由于發(fā)送彈幕的請求數(shù)量較多,而每次發(fā)送彈幕是都需要查詢活動信息,因此活動信息直接從redis查詢得到。
- 由于修改活動信息的請求數(shù)量較少,不妨每次修改活動信息時會同時修改redis和mysql中的活動信息,從而保證了數(shù)據(jù)的一致性。
具體代碼如下
def read_from_cache(attribute, id):
'''
從內(nèi)存中讀取數(shù)據(jù)庫字段
:param attribute: 屬性名
:param id: 數(shù)據(jù)庫記錄的id
:return:
'''
key = attribute + '_' + str(id)
value = cache.get(key)
if value is None:
data = None
else:
data = json.loads(value)
return data
def write_to_cache(attribute, id, value):
'''
向內(nèi)存中寫入數(shù)據(jù)庫字段
:param attribute: 屬性名
:param id: 數(shù)據(jù)庫記錄id
:param value: 寫入的值
:return:
'''
key = str(attribute) + '_' + str(id)
cache.set(key, json.dumps(value), settings.NEVER_REDIS_TIMEOUT)
def get_activity_attribute(activity_id, attribute_name):
'''
從內(nèi)存中讀取與活動相關(guān)的屬性
:param activity_id: 活動id
:param attribute_name: 屬性名
:return: 返回值。如果沒有找到,返回None
'''
data = read_from_cache("activity_"+attribute_name, activity_id)
if data is not None: #如果能在內(nèi)存中查到
print("在內(nèi)存中找到", "屬性名="+attribute_name, "id=",activity_id,"value=", data)
return data #則直接返回
activities = Activity.objects.filter(id=activity_id) # 否則在數(shù)據(jù)庫中進行查找
if len(activities) == 0:
return None
try:
data = activities.values(attribute_name)
data = data[0][attribute_name]
write_to_cache("activity_" + attribute_name, activity_id, data)
return data
except:
return None
def set_activity_attribute(activity_id, attribute_name, value):
'''
向內(nèi)存中寫入與活動相關(guān)的信息
:param activity_id: 活動id
:param attribute_name: 屬性名
:param value: 值
:return: 是否設(shè)置成功
'''
activities = Activity.objects.filter(id=activity_id) # 首先寫到數(shù)據(jù)庫中
if len(activities) == 0:
return False
setattr(activities[0], attribute_name, value)
activities[0].save()
write_to_cache("activity_"+attribute_name, activity_id, value) # 然后在內(nèi)存中更新相應(yīng)字段
return True