redis-keyvalue原理
先总结学到的内容:
一.字典比比列表快
二.优化概率排序
三.整体流程:1.不存在就创建一个字典记录下密码,次数为1。
2.若存在了,就次数+1
3.sorted一般返回的是一个list,然而处理风格是[[“123456”,7]]
4.看17、18行的解释了解到sorted
5.24行有一个内存优化,如何优化的呢,把生成的字典删除因为已经有了所需要的mylist,我眼里mylist就是排了序的csdnpassworddict,因此csdnpassword没了用处
filepath=r"xxx"
csdnfile = open(filepath, "rb")#rb以二进制方式读取文件,改文件必须已经存在
csdnpassworddict={}
while True:
line=csdnfile.readline()
if not line: #最后一句跳出
break
line=line.decode("gbk",errors="ignore")
linelist=line.split(" # ")
password = linelist[1]#密码
if password not in csdnpassworddict:
csdnpassworddict[password]=1
else:
csdnpassworddict[password]=csdnpassworddict[password]+1
csdnfile.close()
print("密码字典生成次数")
#根据key,根据次数排序,排序所有的元素,按照次数,从大到小
#item取出字典里所有的元素,每个字典里既有key又有value;x:x[1]是根据进行次数排序
mylist = sorted(csdnpassworddict.items(),key=lambda x:x[0],reverse=True)
print(type(mylist),"类型")
#[["123456",7]]
print("密码字典排序完成")
del csdnpassworddict #节约内存
print("内存优化")
savefilepath=r"xxxx"
savefile = open(savefilepath,"wb")#以二进制方式写入文件
for key in mylist:
savefile.write((str(key[1])+"#"+key[0]+"\r\n").encode("utf-8"))#\r\n回车换行
savefile.close()
redis数据库数据类型
redis有五种数据类型:string(字符串),hash(哈希),list(列表),set(集合),及zset(sorted set:有序集合)。
redis | 含义 |
---|---|
String | 字符串 |
Hash | 哈希 |
list | 列表 |
Set | 集合 |
Sorted | 有序集合 |
String 字符串
string是 redis最基本的类型,一个 key对应一个 value。 string 类型是二进制安全的。意思是 redis 的 string可以包含任何数据。比如 jpg图片或者序列化的对象 string 类型是 Redis最基本的数据类型,一个键最大能存512MB。
小技巧:set与get是一对,存于取
redis 127.0.0.1:6379> SET name "yincheng"
OK
redis 127.0.0.1:6379> GET name
"yincheng"
127.0.0.1:6379> type name
string
删除键值
redis 127.0.0.1:6379> del name
验证键是否存在
redis 127.0.0.1:6379> exists name
(integer) 0
在上面的例子中,SET 和 GET 是 Redis STRING 命令, name 和 yincheng 是存储在 Redis 的键和字符串
值。
Hash哈希
Redis hash 是一个键值对集合,必须成对出现。
Redis hash是一个 string类型的 field 和 value 的映射表,hash特别适合用于存储对象。
127.0.0.1:6379> HMSET my_hash_table username yincheng age 18 sex
male OK
127.0.0.1:6379> HGETALL my_hash_table
1) "username"
2) "yincheng"
3) "age"
4) "18"
5) "sex"
6) "male"
在上面的例子中,哈希数据类型用于存储包含用户基本信息的用户对象。
这里 HSET,HGETALL 是 Redis HASHES 命令, 同时 my_hash_table 也是一个键。
List 列表
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部
(右边)。
小技巧:lpush=list push lrange=list range lrange需要包括1-3里的一个不然报错误:empty
redis 127.0.0.1:6379> lpush tutorial_list redis
(integer) 1
redis 127.0.0.1:6379> lpush tutorial_list mongodb
(integer) 2
redis 127.0.0.1:6379> lpush tutorial_list rabbitmq
(integer) 3
redis 127.0.0.1:6379> lrange tutorial_list 0 10
1) "rabitmq"
2) "mongodb"
3) "redis"
列表最多可存储 2 32 - 1 元素 (4294967295, 每个列表可存储 40 多亿)。
set集合
Redis Set 是 string 类型的无序集合。 集合是通过哈希表实现的,所以
添加,删除,查找的复杂度都是 O(1)。 在 Redis 可以添加,删除和测试
成员存在的时间复杂度为 O(1)。
小技巧:sadd=set add smembers=set members
Redis 基本数据类型 12
127.0.0.1:6379> sadd myset redis
(integer) 1
127.0.0.1:6379> sadd myset mongodb
(integer) 1
127.0.0.1:6379> sadd myset rabitmq
(integer) 1
127.0.0.1:6379> sadd myset rabitmq
(integer) 0
127.0.0.1:6379> smembers myset
1) "mongodb"
2) "redis"
3) "rabitmq"
注:在上面的例子中 rabitmq 被添加两次,但由于它是只集合具有唯一特性。 集合中最大的成员数
为 2 32 - 1(4294967295, 每个集合可存储 40多亿个成员)。
zset(sorted set:有序集合)
Redis zset 和 set 一样也是 string 类型元素的集合,且不允许重复的成员。 不同的是每个元素都会关联一个
double 类型的分数(权重)。redis 正是通过分数来为集合中的成员(权重)进行
从小到大的排序。
zset 的成员是唯一的,但分数(score)却可以重复
127.0.0.1:6379> zadd mysortset 0 redis
(integer) 1
127.0.0.1:6379> zadd mysortset 2 mongodb
(integer) 1
127.0.0.1:6379> zadd mysortset 1 rabitmq
(integer) 1
127.0.0.1:6379> ZRANGEBYSCORE mysortset 0 1000
1) "redis"
2) "rabitmq"
3) "mongodb"
redis与python之间的链接
直接调用redis库
import redis
#连接数据库
try:
myredis=redis.StrictRedis(host="127.0.0.1",
port=6379,
db=0,
password="")
myredis.set("hello", "密码正确")
print(myredis.get("hello").decode("utf-8"))
myredis.delete("hello")
print(myredis.get("hello").decode("utf-8"))
except:
print("密码错误")
哈希的使用
学到的心得:当出现错误时候,看一下类型,比如这个mydict[b"sunyu"]因为是二进制所以要加一个b。
import redis
myredis = redis.StrictRedis(host="127.0.0.1",
port=6379,
db=0,
password="")
myredis.hset("user:password","yincheng","111111")
myredis.hset("user:password","sunyu","111111abc")
print(myredis.hgetall("user:password"))
mydict=myredis.hgetall("user:password")
print(type(mydict))
print(mydict)
print(mydict[b"sunyu"])#这个属于二进制所以要加b
print(myredis.hkeys("user:password"))#这个代表key
统计次数
并不困难理解起来,链接redis之后,一个类型的次数用incr()来增加
import redis
myredis = redis.StrictRedis(host="127.0.0.1",
port=6379,
db=0,
password="")
myredis.set("qazwsx",2000)
myredis.incr("qazwsx")#相当于次数加一
myredis.incr("qazwsx")
print(myredis.get("qazwsx"))
print(myredis.get("qazwsxedc"))#None表示不存在,存在返回值
pipeline通道
对于通道的理解:线程可能会有多个,那么就把所有线程都开始加入通道运行,之后直接读取所有的结果,如果里面有一个错误,那么就报错。
import redis
myredis = redis.StrictRedis(host="127.0.0.1",
port=6379,
db=0,
password="")
myp=myredis.pipeline()#构建一个管道 提问:什么是管道?
myp.set("gaoqinghua","baby")
myp.sadd("hechengcheng","go")#set add 简称sadd
myp.execute()#执行
print(myredis.get('gaoqinghua'))
订阅
自己的理解:给一个频道发消息,底下所有的订阅者都能收到,看一下给的解释吧。
应用场景
在 Redis 中,你可以设定对某一个 key 值进行消息发布及消息订阅,当一个 key 值上进行了消息发布后,所
有 订阅它的客户端都会收到相应的消息。这一功能最明显的用法就是用作实时消息系统,比如普通的即
时聊 天,群聊等功能。
- 今日头条订阅号、微信订阅公众号、新浪微博关注、邮件订阅系统
- 即时通信系统(QQ、微信)
- 群聊部落系统(微信群)
这个案例视频没给出,但在文档中用了,比较好理解:
案例
微信班级群 class:20170101,发布订阅模型
学生A B C
订阅一个主题名叫:class20170101
127.0.0.1:6379> SUBSCRIBE class:20170101
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1
学生A:
针对 class:20170101 主题发送 消息,那么所有订阅该主题的用户都能够收到该数据。
127.0.0.1:6379> PUBLISH class:20170101 "i love peace!"
(integer) 1
学生B:
针对 class:20170101 主题发送 消息,那么所有订阅该主题的用户都能够收到该数据。
127.0.0.1:6379> PUBLISH class:20170101 "go to hell"
(integer) 1
最后学生C会收到A和B发送过来的消息:
python@ubuntu:~$ redis-cli
127.0.0.1:6379> SUBSCRIBE class:20170101
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "class:20170101"
3) (integer) 1
1) "message"
2) "class:20170101"
3) "i love peace!"
1) "message"
2) "class:20170101"
3) "i love peace!"
1) "message"
2) "class:20170101"
3) "go to hell"