標籤:

知乎是如何做緩存的?

最近準備做一個網站, 架構和知乎差不多,使用tornado框架,mysql作為資料庫,使用SqlAlchemy 為ORM進行資料庫操作,考慮到網站性能,準備加入redis做緩存,但對於sqlalchemy如何結合redis做緩存,不是很懂,請問知乎是如何做緩存的?


受邀請回答。

我不知道知乎是如何做緩存的,但是可以分享一下我用SQLAlchemy和Redis做緩存的做法。

假設有這樣的資料庫表,簡單的博客文章,文章Tag表,按照標準範式表設計,在SQLAlchemy(類似Django的Models範式)設計如下:

class Blog(Models):
__tablename__ = "blog"
id = Column(Integer, primary_key=True)
blog_text = Text()

class BlogTagRel(Models):
__tablename__ = "blogtagrel"
# id = Column(Integer, primary_key=True)
blog_id = Column(Integer)
tag_id = Column(Integer)

class Tag(Models):
__tablename__ = "tag"
id = Column(Integer, primary_key=True)
tag_text = Text()

這個基本是最基本的一對多的範例,那麼規劃自己的Redis緩存使用的數據類型,規劃如下(類似C的偽代碼,將就看看,大體理解,輕拍):

Redis緩存的Key大體按照 Table-Name: Primary-Key: Column-Key = Column-Value 這樣設計。

blog:(id): text = [string] text
blog:(id):tags = [hashs]
[string] tag1
[string] tag2
.......

上面是Models的設計和緩存設計,現在設計Backend類,關鍵的將兩者整合起來的後端實現,ORM+緩存。

class Backend(): # 偽代碼,輕拍
# CURD的Create
def create_blog(self, blog_text):
# 寫入資料庫
blog = Blog(blog_text=blog_text)
sqlalchemy_session.add(blog)
sqlalchemy_session.commit()
# 寫入緩存
redis_conn.set("blog:" + blog.id + ":text", blog_text)
# CURD的Read
def read_blog(self, id):
# 檢查緩存是否存在
if redis_conn.exists("blog:" + blog.id + ":text"):
return redis_conn.get("blog:" + blog.id + ":text")
else:
blog = sqlalchemy_session.query(Blog).filter_by(id=id).first()
# 寫入緩存
redis_conn.set("blog:" + blog.id + ":text", blog.blog_text)
return blog

使用的時候,直接就是Backend.create_blog()和Backend.read_blog(),這樣就可以整合SQLAlchemy和Redis的緩存。

上面的代碼還有些問題,比如SQLAlchemy返回的數據是需要和Redis返回的緩存數據是一致的,這樣方便外部的邏輯實現調用吧。但是上面的思路就是這樣的,ORM + Cache = Backend,外部統一調用Backend的邏輯。ORM你可以寫成Raw SQL,Cache可以換任何的Memcached等的緩存,但實現思路是一樣的。

很簡潔是不是?哈哈。

希望對你有用。

希望知乎分享一下Redis的緩存經驗,或者是緩存的架構:)


從(怎麼使用)工具出發來設計性能,有這種思路的話一上來就錯了

性能設計的正途是充分研究業務的數據流,充分利用(exploit)數據的特性來削減運算、避免瓶頸。至於那些工具只是給你參考的,就算要用最好也是拆了、消化了、自己改造了再用


沒做過這些呢,一直溜達在web中,對大數據只使用過oracle的表分區,對於緩存技術層面的還停留在ibatis的緩存技術,呵呵,只是做web開發的,有時間準備下一步學習下hadoop啥的


推薦閱讀:

redis相對於mysql有什麼劣勢,是不是能用redis盡量用?
隊列是什麼意思?
Redis內部數據結構詳解(5)——quicklist
scrapy-redis 和 scrapy 有什麼區別?

TAG:Redis |