1 前言
最早的排行榜,起源于在魔兽世界游戏的拍卖行,常规数据库mysql无法实现这一功能,但是redis可以解决。
redis的有序集合,可以实现这一功能。有序集合的底层是哈希(可以去重)和链表(指针,指向下一个元素的内存地址,方便插入)的结合。
- 数组:某一数组的某一位置插入元祖,巨大成本错位,数组的缺陷(但是查询快),可以折半查找
- 链表:链表查询慢,但是插入快,不能做折半查找,不知道长度,指针指向内存地址,无序,顺序查找(一个一个进行比对),for循环,跳表(123456789,查13579,跳跃性查找,弊端:把奇数节点拿到了,原节点不能删除,平白无故多了百分之五十的存储空间,以空间换时间)
为什么有序集合,确保唯一性,有序
2 redis相关
Microsoft Windows [版本 10.0.17763.1518]
(c) 2018 Microsoft Corporation。保留所有权利。
C:Users86156>redis-cli
127.0.0.1:6379> select 8
OK
127.0.0.1:6379[8]> zadd myscore 3 a # 插入
(integer) 1
127.0.0.1:6379[8]> zadd myscore 4 b
(integer) 1
127.0.0.1:6379[8]> zincrby myscore 5 a # 自增
"8"
127.0.0.1:6379[8]> zrange myscore 0 10 # 获取(django中是列表)
1) "b"
2) "a"
127.0.0.1:6379[8]> zscore myscore a
"8"
127.0.0.1:6379[8]> zscore myscore c
(nil)
3 实战代码
- redis里面只需要加几行代码,并新写一个视图函数
# 排序所需代码
r = redis.Redis(db=9, decode_responses=True)
m = r.zscore('money', user_id)
# 如果有数据,要自增
if m:
r.zincrby(user_id, user_id, money)
# 没有的话,直接插入即可
r.zadd('money', {user_id: money})
from rest_framework.response import Response
from rest_framework.views import APIView
from userapp.models import UserModel
# 写一个新的视图函数
class ScoreView(APIView):
def get(self, request):
import redis
r = redis.Redis(db=9, decode_responses=True)
list = r.zrange('money', 0, 10)
score_list = []
for i in list[::-1]:
dict = {}
username = UserModel.objects.get(pk=i).username
value = r.zscore('money', i)
dict['username'] = username
dict['money'] = value
score_list.append(dict)
return Response({'data':score_list})