优点
- 内存型数据库,读写速度快
- 支持的数据类型丰富
- 支持事务
- 特性丰富, 可用于缓存、消息队列、按 key 设置过期时间
数据类型
1.string
可存储字符串和数值,常见的操作包括:
插入数据 set set key value
批量插入 mset set k1 v1 k2 v2
获取数据 get get key
批量获取 mget mget k1 k2
删除数据 del del key
追加数据 append append key add_str
写入新数据并获取老数据 getset getset key value
获取长度 strlen
自增1 incr incr key
按需自增 incrby incr key add_number
按需自增小数 incrbyfloat incrbyfloat key add_float
自减1 decr decr key
按需自减 decrby decr key add_number
设置过期时间 setex setex key seconds value
获取剩余过期时间 ttl ttl key
字符串替换 setrange setrange key index add_str
获取子串 getrange getrange key index count
[奇怪的操作]
setnx 命令
setnx name Tom
如果name键不存在,则不赋值,返回0;反之则赋值,返回1
批量设置 msetnx
msetnx k1 v1 k1 v1
这些k、v的设置如果有一个失败,则全失败
总结:对整个字符串或者字符串中的其中一部分执行操作;对整数和浮点数执行自增或者自减操作.
2. list
左边插入元素 lpush lpush key v1 v2 v3
右边插入元素 rpush rpush key v2 v2 v3
key存在时则左边插入 lpushx lpushx key v1
key存在时则右边插入 rpushx rpushx key v1
左边弹出元素 lpop lpop key
右边弹出元素 rpop rpop key
获取列表长度 llen llen key
获取列表片段值 lrange lrange key start end
保留列表指定片段 ltrim ltrim key start end
删除指定个数的元素 lrem lrem key count value
设定指定索引的值 lset lset key index value
在指定的位置插入元素 linsert linsert key before/after old_value v1
获取指定索引的值 lindex lindex key index
将元素从一个列表转移至另一个列表
rpoplpush rpoplpush key1 key2
注意:没有rpoprpush、lpoplpush、lpoprpush等命令
总结:从两端压入或者弹出元素;对单个或多个元素进行修剪,只保留一个范围内的元素
3.hash
设置字段值 hset hset key field value
批量设置 hmset hmset key f1 v1 f2 v2 f3 v3
获取字段值 hget hget key field
批量获取字段 hmget hmget key f1 f2 f3
批量删除字段 hdel hdel key f1 f2
判断字段是否存在 hexists hexists key field
获取字段数量 hlen hlen key
字段值自增 hincrby hincrby key field add_number
获取所有字段/值 hgetall hgetall key
获取所有字段名 hkeys hkeys key
获取所有字段值 hvals hvals key
总结:添加、获取、移除单个键值对;获取所有键值对;检查某个键是否存在
4.set
增加元素(批量) sadd sadd key m1 m2 m3
获取元素个数 scard scard key
判断元素是否在集合中 sismember sismember key member
获取集合所有元素 smembers smembers key
从集合弹出一个元素 spop spop key
从集合随机获取多个元素 srandmember srandmember key count
删除元素 srem srem key m1 m2 m3
将元素从集合1转移到集合2 smove smove src dst member
集合差集运算 sdiff sdiff key1 key2
集合差集运算并保存 sdiffstore sdiffstore dst key1 key2
集合交集运算 sinter sinter key1 key2
集合交集运算并保存 sinterstore sinterstore dst key1 key2
集合并集运算 sunion sunion key1 key2
集合并集运算并保存 sunionstore sunionstore dst key1 key2
总结:添加、获取、移除单个元素;检查一个元素是否存在于集合中;计算交集、并集、差集;
从集合中随机获取元素
5.zset
说明:与set不同的是,zset有序集合,每个元素都有一个分数与之关联,zset就是根据分数来对成员进行
从小到大的排序。
增加元素(批量) zadd zadd key s1 m1 s2 m2 s3 m3
统计所有元素 zcard zcard key
统计指定分数范围内元素 zount zcount key minscore maxscore
获取元素分数 zscore zscore key member
增加某个元素的分数 zincrby zincrby key increment member
[不同的排序获取方法]
获取排名范围内的元素 zrange zrange key start stop [withscores]
获取排名范围内的元素(降序) zrevrange zrevrange key start stop [withscores]
获取分数范围内的元素 zrangebyscore
zrangebyscore key minscore maxscore [withscores] [limit offset count]
获取分数范围内的元素(降序) zrevrangebyscore
zrevrangebyscore key maxscore minscore [withscores] [limit offset count]
获取元素排名 zrank zrank key member
获取元素排名(降序) zrevrank zrevrank key member
[删除元素]
批量删除元素 zrem zrem key m1 m2 m3
按照排名范围删除元素 zremrangebyrank
zremrangebyrank key start stop
按照分数范围删除元素 zremrangebyscore
zremrangescore key minscore maxscore
总结:添加、获取、删除元素;根据分值范围或者成员来获取元素;计算一个键的排名
6.其他命令
获取匹配模式的key keys keys pattern
获取所有key keys *
获取键类型 type type key
判断键是否存在 exists exists key
批量删除键 del del key1 key2
设置key的过期时间 expire expire key seconds
获取key的剩余过期时间 ttl ttl key
应用场景
1.缓存
这是最常见的使用方法。缓存历史数据或者不需要暴露给前端的数据。
2.计数器
访问量统计这种功能就可以采用string类型来做。
3.排行榜
可以使用list或者zset来做
4.消息队列
选用list
5.发布订阅
subscribe命令和publish命令配合使用
Redis与Memcached 区别
1.持久化
Memcached把数据全部保存在内存中,没有持久化,如果服务器挂掉,数据会丢失
Redis有持久化机制RDB、AOF,可以保存数据到磁盘,如此当服务器挂掉后,可以从磁盘恢复数据
2.支持的数据类型
Memcached仅支持string类型
Redis除了string类型,还支持list、hash、set、zset等类型
3.网络IO模式
Memcacahed 是多线程的网络模式
Redis是单进程单线程的IO多路复用模型
4.数据一致性
Memcached使用cas保证高并发访问时的数据一致性
Redis提供事务来保证数据一致性
过期机制
1.定期删除,定期查找已设置过期时间的数据是否有过期数据
2.lazy删除,在需要使用时,查询是否达到过期时间,若是,删除数据
3.定时删除,根据过期时间设置定时,在过期时间来临时,删除数据
Redis使用的是1+2过期机制
持久化机制
Redis是内存型数据库,为了保证数据在断电后不会丢失,需要将内存中的数据持久化到硬盘上,
目前redis提供RDB和AOF两种持久化策略。
1.RDB
将某个时间点的所有数据快照都保存到硬盘上,默认保存到dump.rdb文件。
优点:方便备份;RDB在恢复大数据时比AOF更快
缺点:使用RDB备份,就有可能丢失RDB之后的数据;如果保存的数据较多,会占用较多的内存资源
2.AOF
将每一个收到的写命令追加到文件中,默认保存到appendonly.aof文件。
优点:比RDB丢失的数据更少,AOF重写机制;
缺点:同样数据集下aof文件要比rdb文件大;恢复速度慢
回收机制
1.为啥需要回收机制?
因为可以设置redis内存最大使用量,而且内存自身的资源也是有限的,需要设定垃圾回收机制,
从而确保redis的良性运转。
2.回收机制的基本手段有哪些?
删除过期的键;内存使用达到maxmemory时触发内存溢出控制策略。
3.内存溢出控制策略有哪些?
[1]从已设置过期时间的数据集中挑选最近最少使用的数据进行淘汰
[2]从已设置过期时间的数据集中挑选将要过期的数据淘汰
[3]从已设置过期时间的数据集中随机选择数据淘汰
[4]从所有数据集中淘选最近使用最少的数据淘汰
[5]从所有数据中随机选择数据进行淘汰
[6]当内存不足时,禁止写入新数据
其中方案[1]、方案[4]比较适用, 且都属于LRU算法。
4.LRU算法
算法依据:如果数据最近被访问过,那么将来被访问的几率也更高;相反,如果数据长期没有被访问过,
那么将来被访问的几率也更低。
实现例子:
from collections import OrderedDict
class LRUCache(OrderedDict):
def __init__(self, capacity):
self.capacity = capacity
self.cache = OrderedDict()
def get(self, key):
"""获取键值
1.如果键不存在,则直接返回 None
2.如果键存在,则先需要把键从 缓存 中弹出,然后添加到末尾(表示最近使用到了)
"""
if key in self.cache:
value = self.cache.pop(key)
self.cache[key] = value
else:
value = None
return value
def set(self, key, value):
"""
1.如果键存在,则将键从 缓存 中弹出,然后把 键和新值 添加到末尾;
2.如果键不存在,则需要判断 缓存 是否已满
如果缓存没满,直接在末尾添加元素即可;
如果缓存满了,则需要将第一个键弹出,然后在末尾添加新键
"""
if key in self.cache:
old_value = self.cache.pop(key)
self.cache[key] = value
else:
if len(self.cache) == self.capacity:
self.cache.popitem(last=False) # pop出第一个item
self.cache[key] = value
else:
self.cache[key] = value
测试
c = LRUCache(5)
for i in range(5,10):
c.set(i,10*i)
print c.cache, c.cache.keys()
c.get(5)
c.get(7)
print c.cache, c.cache.keys()