一、常见应用场景
1.会话存储
在现代的架构中,通常多个服务器位于一个或多个负载均衡器之后。会话(Session)通常需要存储在外部存储系统中。如果有一个服务器宕机,其他的服务器可以从外部存储中获取会话并继续服务。因为与关系数据库相比Redis的访问延迟非常低,所以使用Redis来保存会话数据堪称是一种完美的会话存储机制。并且Redis中对键过期的支持可以天然地用于会话的超时管理。
2.分析
还可以用于统计分析的场景。例如,如果想要计算某个功能被使用了多少次,或者想要计算某个API被调用的次数,那么简单地使用INCR命令增加某功能的被点击次数或某API的被调用次数的计数器即可;甚至还可以结合Lua脚本限制公开 API 的请求次数(将 API 的最大请求数限制在每个 IP 地址每秒钟十个之内)。因为所有的Redis命令都是原子的,所以无需担心竞态。基于诸如哈希、有序集合和HyperLoglog等数据类型,还可以构建其他更高级的计数器或统计数据捕获系统。
3.排行榜
利用有序集合(Sorted Set),就可以轻松地实现一个排行榜。例如:可以为投票目标创建一个有序集合并将用户的投票数作为权重。因此,使用ZREVRANGE命令就能够按照投票目标的受欢迎程度返回投票目标的列表。同样的功能也可以在关系数据库中实现,但是SQL查询要比Redis查询慢得多。
4.队列
利用列表(List)的PUSH/POP命令(阻塞类型)就能实现任务队列。例如:先使用BLPOP命令从任务列表左端移除并获取第一个任务(没有的时候则阻塞了),相当于获取任务;然后使用RPUSH命令从任务列表右端插入一个新任务,相当于分配任务;此时刚才排队获取任务的客户端就能第一时间拿到新任务。
5.最新的N个记录
假设我们想要获取最近新签的10个合同,通常采用一个SQL查询:select top 10 * from contract order by signtime desc
而采用Redis解决则可以先创建一个列表,新签的合同采用LPUSH命令插入,然后再执行LTRIM命令只保留10个元素。
6.缓存
例如:在查询关系数据库之前,我们首先在Redis中查找记录。如果在Redis中找不到记录,则查询关系数据库并将记录放到Redis中。在向关系数据库写入时,我们也同时将记录写入Redis。为了限制缓存的大小,可以对缓存中的记录设置过期时间或应用诸如最近最少使用(LeastRecentlyUsed,LRU)的收回策略。
二、使用正确的数据类型
时间-空间的平衡
例如:10000个用户信息(id,name,sex,age,registertime)
1.首先存储为字符串类型的键值对,内存消耗4.04M;
2.改为哈希类型,内存消耗2.29M左右,此时节省了约43%((4.04-2.29)/4.04)的内存空间;
3.改为将一个用户信息存储为一个json字符串,内存消耗2.29M,与哈希类型所消耗内存几乎相同(键的数量并没有减少);
4.使用Lua脚本,利用msgpack库(https://msgpack.org/)序列化原始json字符串,内存消耗2.06M,此时节省了约49%((4.04-2.06)/4.04)的内存空间;
5.
又例如:计数时可以使用集合、位图或HyperLogLog
官方一些内存优化的案例:https://redis.io/topics/memory-optimization
三、使用正确的Redis API
保证性能
1.尽量将数据操作组合在一起来降低往返延时(RTT),采用管道,采用批量处理的API;
2.因为Redis是单线程的数据存储服务,所以应该多考虑API的时间复杂度,避免阻塞服务器。
四、使用C#连接到Redis
通过VS(Visual Studio 2017)创建一个控制台应用程序
通过NuGet获取StackExchange.Redis
简单示例
使用管道(事务类似)
运行Lua脚本
local id = @key
local data = @arg
local dataSource = cjson.decode(data)
local retJson = redis.call('get', id)
if retJson == false then
retJson = {}
else
retJson = cjson.decode(retJson)
end
for k,v in pairs(dataSource) do
retJson[k] = v
end
redis.call('set', id, cjson.encode(retJson))
return redis.call('get', id)
五、使用Python连接到Redis
Python(https://www.python.org/),我此时使用的是Python3.7.1
通过PyPI安装redis-py:执行命令pip install redis
通过VS(Visual Studio 2017)创建一个Python应用程序
简单示例
示例程序输出结果如下:
使用管道
输出结果将显示对应响应的列表
运行Lua脚本
local id = KEYS[1]
local data = ARGV[1]
local dataSource = cjson.decode(data)
local retJson = redis.call('get', id)
if retJson == false then
retJson = {}
else
retJson = cjson.decode(retJson)
end
for k,v in pairs(dataSource) do
retJson[k] = v
end
redis.call('set', id, cjson.encode(retJson))
return redis.call('get', id)
执行结果输出的是更新后的json
六、使用Redis编写MapReduce作业
七、使用Redis编写Spark作业