Redis(Remote Dictionary Server)
Redis是一个开源的使用C语言编写、支持网络、可基于内存亦可持久化的日志型、key-value数据库,并提供多种语言的API。
与传统数据库不同的是redis的数据是存在内存中的,所以读写速度非常快,因此redis被广泛应用于缓存方向。另外,redis也经常用来做分布式锁。Redis提供了多种数据类型来支持不同的业务场景。除此之外,redis支持事务、持久化、LUA脚本、LRU驱动事件、多种集群方案。
为什么要用redis/为什么要用缓存-->高性能;高并发
为什么要用redis而不用map/guava做缓存?
缓存分为本地缓存和分布式缓存。以Java为例,使用自带的map或者guava实现的是本地缓存,最主要的特点是轻量以及快速,生命周期随着jvm的销毁而结束,并且在多实例的情况下,每个实例都需要各自保存一份缓存,缓存不具有一致性
使用redis或memcached之类的称为分布式缓存,在多实例的情况下,各实例共用一份缓存数据,缓存具有一致性。缺点是需要保持redis或memcached服务的高可用,整个程序架构上较为复杂。
redis的线程模型
redis内部使用文件事件处理器file event handler,这个文件事件处理器是单线程的,所以redis才叫做单线程的模型。它采用IO多路复用机制同时监听多个socket,根据socket上的事件来选择对应的事件处理器进行处理。
文件事件处理器的结构包含4个部分:
多个socket;IO多路复用程序;文件事件分派器;事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)
多个socket可能会并发产生不同的操作,每个操作对应不同的文件事件,但是IO多路复用程序会监听多个socket,会将socket产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理
redis和memcached的区别
1.redis支持更丰富的数据类型(支持更复杂的应用场景):Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。memcached支持简单的数据类型,String。
2.redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而Memecache把数据全部存在内存之中
3.集群模式,memcached没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;但是redis目前是原生支持cluster模式的
4.Memcached是多线程,非阻塞IO复用的网络模型;Redis使用单线程的多路IO复用模型
验证redis是否启动:
ps -ef|grep redis
lsof -i:6379
netstat
分布式数据库中CAP原理:CAP+BASE
一致性:一致性指的是多个数据副本是否能保持一致的特性,在一致性的条件下,系统在执行数据更新操作之后能够从一致性状态转移到另一个一致性状态。对系统的一个数据更新成功之后,如果所有用户都能够读取到最新的值,该系统就被认为具有强一致性。
可用性:可用性指分布式系统在面对各种异常时可以提供正常服务的能力,可以用系统可用时间占总时间的比值来衡量,4个9的可用性表示系统99.99%的时间是可用的。在可用性条件下,要求系统提供的服务一直处于可用的状态,对于用户的每一个操作请求总是能够在有限的时间内返回结果。
分区容忍性:网络分区指分布式系统中的节点被划分为多个区域,每个区域内部都可以通信,但是区域之间无法通信。在分区容忍性条件下,分布式系统在遇到任何网络分区故障的时候,仍然需要能对外提供一致性和可用性的服务,除非是整个网络环境都发生了故障。
权衡:在分布式系统中,分区容忍性必不可少,因为需要总是假设网络是不可靠的。因此,CAP理论实际上是要在可用性和一致性之间做权衡
可用性和一致性往往是冲突的,很难使它们同时满足。在多个节点之间进行数据同步时,
为了保证一致性(CP),不能访问未同步完成的节点,也就失去了部分可用性
为了保证可用性(AP),允许读取所有节点的数据,但是数据可能不一致
传统的ACID:原子性、一致性、独立性、持久性
CAP:强一致性、可用性、分区容错性
CAP理论的核心是:一个分布式系统不可能同时很好的满足这三个,最多只能同时较好的满足两个
CA-单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大 传统Oracle
--------------------------->NoSQL数据库必须包含P
CP-满足一致性,分区容忍性的系统,通常性能不是特别高 Redis、Mongodb
AP-满足可用性,分区容忍性的系统,通常可能对一致性要求低一些 大多数网站架构的选择
数据库事务一致性需求:
BASE:
分布式:
集群:
Redis常见数据结构-->五大数据类型:String、List、Set、Hash、Zset
Redis键key
redis键命令的基本语法:COMMAND KEY_NAME
Redis keys命令:
DEL key:该命令用于在key存在时删除key
DUMP key:序列化给定key,并返回被序列化的值
EXISTS key:检查给定key是否存在
EXPIRE key seconds:设置过期时间,过期删除
PEXPIRE key milliseconds:设置key的过期时间以毫秒计
KEYS pattern:查找所有符合给定模式的key
move key db:将当前数据库的key移动到给定的数据库db当中
ttl key:以秒为单位,返回key的剩余生存时间
type key:返回key所存储的值的类型
set key k:覆盖
Binary-safe strings:string 一个key对应一个value,string类型是二进制安全的,意思是redis的string可以包含任何数据,比如jpg图片或者序列化的对象。string类型是redis最基本的数据类型,一个redis中字符串value最多可以是512M String数据结构是简单的key-value类型,value不仅可以是String,也可以是数字。常规key-value缓存应用;常规计数:微博数,粉丝数等。
常用命令:SET key value 设置指定key的值
GET key 获取指定key的值
GETRANGE key start end 返回key中字符串值的子字符
GETSET key value 将给定key的值设为value,并返回key的旧值
GETBIT key offset 对key所存储的字符串值,获取指定偏移量上的位
MGET key1 key2 获取所有(一个或多个)给定key的值
SETBIT key offset value 对key所存储的字符串值,设置或清楚指定偏移量上的位
SETEX key seconds value 将值value关联到key,并将key的过期时间设为seconds
SETNX key value 只有在key不存在时设置key的值
SETRANGE key offset value 用value参数覆写给定key所存储的字符串值,从偏移量offset开始
STRLEN key 返回key所存储的字符串值的长度
MSET key value key value 同时设置一个或多个key-value对
MSETNX key value key value 同时设置一个或多个key-value对,当且仅当所有给定key都不存在
INCR key
INCRBY key increment
DECR key
DECRBY key decrement
Append key value
set/get/del/append/strlen append key value
INCR(自增1) key / DECR key / INCRBY key increment / DECRBY key decrement
getrange key start end 相当于between and
setrange key xxxx
setex(set with expire)键秒值/setnx(set if not exist)
mset/mget/msetnx
Hash:键值对集合,是一个string类型的field和value的映射表,hash特别适合用于存储对象,后续操作的时候,可以直接仅仅修改这个对象中的某个字段的值。常用命令:hget,hset,hgetall等
KV模式不变,但V是一个键值对
hset/hget/hmset/hmget/hgetall/hdel
hlen
hexists key 在key里面的某个值的key
hkeys/hvals
hash是一个string类型的field和value的映射表,hash特别适合用于存储对象,后续操作的时候,可以直接仅仅修改这个对象中的某个字段的值。比如可以hash数据结构来存储用户信息,商品信息等等
常用命令:HDEL key field1 [field2] 删除一个或多个哈希表字段
HEXISTS key field 查看哈希表key中,指定的字段是否存在
HGET key field 获取存储在哈希表中指定字段的值
HGETALL key 获取在哈希表中指定key的所有字段和值
HINCRBY key field increment 为哈希表key中的指定字段的整数值加上增量increment
HINCRYBYFLOAT key field increment 为哈希表key中的指定字段的浮点数值加上增量increment
HKEYS key 获取所有哈希表中的字段
HLEN key 获取哈希表中字段的数量
HMGET key field1 field2 获取所有给定字段的值
HMSET key field1 value1 field2 value2 同时将多个field-value对设置到哈希表key中
HSET key field value 将哈希表key中的字段field的值设为value
HSETNX key field value 只有在字段field不存在时,设置哈希表字段的值
HVALS key 获取哈希表中所有值
List:LinkedList
一个字符串链表,left、right都可以插入添加
如果键不存在,创建新的链表 ;如果键已存在,新增内容; 如果值全移除,对应的键也就消失了
list就是链表,Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如微博的关注列表,粉丝列表,消息列表等功能都可以用Redis的list结构来实现。
Redis list的实现为一个双向链表,可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销
可以通过lrange命令,就是从某个元素开始读取多少个元素,可以基于list实现分页查询,基于redis实现简单的高性能分页,可以做类似微博那种下拉不断分页的东西,性能高
常用命令:
lpush/rpush key value1 value2 将一个或多个值插入到列表头部
lrange key start stop 获取列表指定范围内的元素
lpop/rpop key 移出并获取列表的第一个元素
lindex key index 通过索引获取列表中的元素
llen key 获取列表长度
lrem n key 删除n个key
ltrim key 开始index 结束index 截取指定范围的值后再赋给key
rpoplpush 源列表 目的列表
lset key index value 通过索引设置列表元素的值
linsert key before|after pivot value 在列表的元素前或者后插入元素
Sets:string类型的无序集合,是通过hashtable实现的
sadd/smembers/sismember SADD key member1 member2 向集合添加一个或多个成员
scard key,获取集合里面的元素个数
srem key value 删除集合中元素
srandmember key 某个整数,随机出几个数
spop key 随机出栈 移除并返回集合中的一个随机元素
差集:sdiff 在第一个set里面而不再后面任何一个set里面
交集:sinter 返回给定所有集合的交集
并集:sunion 返回给定所有集合的并集
set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的。
当需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。可以基于set轻易实现交集、并集、差集的操作
比如在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis可以非常方便的实现如共同关注、共同粉丝、共同喜好等功能。
Sorted Sets:和set一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数,redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数却可以重复。
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
常用命令:zadd,zrange,zrem,zcard等
和set相比,sorted set增加了一个权重参数score,使得集合中的元素能够按score进行有序排列
比如在直播系统中,实时排行信息包含直播间在线用户列表,各种礼物排行榜,弹幕消息