C语言开发的
TCP协议读写
数据都存储在内存中,可达到10万个键值读写每秒。
支持持久化。
还能够限定数据占用的最大内存空间,数据量达到空间限制后会按必定的规则自动淘汰不须要的键。
除了缓存,还能够利用列表类型键实现队列,并支持阻塞读取。还有“发布/订阅”的消息模式,作分布式锁。
https://gist.github.com/348262 这是一个用redis实现的聊天室 git
单线程,对手Memcached支持多线程,但redis性能已经足够优异。
redis的优点是支持字符串之外的其余数据类型,还支持持久化。github
纯内存操做
单线程操做,避免了频繁的上下文切换
采用了非阻塞I/O多路复用机制
redis线程模型:
redis-client在操做的时候,会产生具备不一样事件类型的socket。在服务端,有一段I/0多路复用程序,将其置入队列之中。而后,文件事件分派器,依次去队列中取,转发到不一样的事件处理器中。redis
轻量级,一个空redis实例内存只有1MB左右。 算法
第一个小数点后的数字是偶数的版本是稳定版
redis-benchmark 是redis性能测试工具
redis-check-aof 是AOF文件修复工具
redis-check-dump 是RDB文件检查工具 数据库
生产环境推荐使用脚本启动redis,使得redis能随系统自动运行。
将redis源代码目录utils里的redis_init_script脚本,拷贝到/etc/init.d目录中,重命名文件为redis_6379。
新建/etc/redis目录存放配置文件(6379.conf),新建/var/redis/6379文件夹存放redis持久化文件。 json
shutdown中止服务时,redis收到SHUTDOWN命令后会先断开全部客户端链接,而后根据配置执行持久化,最后完成退出。
使用kill
也能够正常中止redis服务。缓存
0-15一个16个库,默认使用第0号库。
redis不支持自定义数据库名,也不支持为每一个库设置不一样的密码。
数据库之间也不是彻底隔离,FLUSHALL
命令能够清空一个redis实例中全部库的数据。
因此这些数据库更像是一种命名空间,不适合存储不一样应用程序的数据,能够存储不一样环境如测试、生产环境的数据。服务器
String
value能够是String也能够是数字。通常作一些复杂的计数功能的缓存,还能够存储json化的对象,甚至是图片(二进制数据),最大容量是512MB(看具体版本)。
hash
注意不能嵌套其余的数据类型(其余的也是),字段值只能是字符串。
通常存放的是结构化的对象,使用对象类型:对象id
构成键名,使用字段表示对象属性,字段值存放属性值。比较方便的操做其中的某个字段。否则使用多个string类型存储一个对象的不一样属性会很差管理。
也能够存映射关系,如搭建博客网站时用散列类型存储文章缩略名slug和id之间的映射关系。
在作单点登陆的时候,用这种数据结构存储用户信息,以cookieId做为key,设置30分钟为缓存过时时间,能很好的模拟出相似session的效果。
list
列表类型能够存储一个有序(指的是插入顺序)的字符串列表。
内部是双向链表。获取头部或尾部的topn会比较快。插入数据的速度也不会受已有数据数量的影响。
能够作简单的消息队列的功能。不一样方向插入、弹出便可。
另外能够用列表类型存储id列表,利用分片获取命令,作基于redis的分页功能。
set
由于set堆放的是一堆不重复值的集合。内部是使用值为空的散列表实现的。最方便的是能够进行交集、并集、差集等运算。
能够存储标签。能够利用集合类型优点的场景。
sorted set
sorted set是使用散列表和跳跃表实现的。与普通集合相比,多了一个权重参数score,集合中的元素可以按score进行排列。能够作排行榜应用,取TOP N操做。
大小写不敏感 $ redis-cli PING
若是链接正常会受到PONG的回复,用来测试客户端与redis的链接是否正常(也能够直接> PING
)。 $ redis-cli -h 127.0.0.1 -p 6379
进入交互模式 > flushdb
清空当前数据库。 > flushall
清空全部数据库。> select [index]
选择索引数据库,index为索引值名,如:select 1
。> quit
退出客户端链接。cookie
查看当前库有哪些键KEYS (pattern)
:session
支持*
、?
、[]
、\x
(表示匹配字符x,如匹配问好,就 KEYS \?
)
须要遍历全部键,当数据量多时,不建议使用。
EXISTS (键名)
判断一个键是否存在,存在则返回1,不然0。 DEL (键名,多个键空格隔开)
删除键,返回值是删除的个数。
能够经过管道实现通配删除:redis-cli KEYS "user:*" | xargs redis-cli DEL
删除全部以"user:"开头的键。或者redis-cli DEL 'redis-cli KEYS "user:*"'
TYPE (键名)
得到键值的数据类型。
STRLEN (键名)
得到键值的长度(中文的话,计算的是utf-8编码后的长度)。不存在,返回0。
========string类型值SET (键名) (值)
赋字符串类型值。项目中键的命名有个建议是对象类型:对象id:对象属性
GET (键名)
当键不存在时会返回空。
MSET (键名) (值)
能够设置多个键值。MGET (键名)
当键不存在时会返回空。
虽然没有整数类型,但也提供了用于整数操做的命令,如INCR
:
经常使用于统计文章访问量等。
INCRBY (键名) (步长)
递增非1的状况使用。若是要递增浮点数,使用INCRBYFLOAT
。
一样,INCR
均可以换为DECR
实现递减。
APPEND (键名) (带双引号的字符串)
实现向键值末尾追加。若键不存在,则至关于在null里追加。
========hash类型值
HSET 键名 字段名 字段值
用来给hash类型数据赋值即插入(返回1),也多是更新(返回0)。HSETNX 键名 字段名 字段值
与上面的区别是若是字段已经存在,不会执行返回0。HGET 键名 字段名
HMSET 键名 (字段名1 字段值1) (字段名2 字段值2) (字段名3 字段值3)...
HMGET 键名 (字段名1) (字段名2) (字段名3)
同时获取多个字段值HGETALL 键名
获取全部键值HEXISTS 键名 字段名
判断一个字段是否存在,存在则返回1,不然(以及键不存在时)返回0。
HINCRBY 键名 字段名 步长
使指定字段的字段值增长指定的整数。不存在的键会自动被创建。
HDEL 键名 字段名1 2 3
能够删除一个或多个字段,返回删除字段的个数。
HKEYS 键名
或 HVALS 键名
分别获取该键的全部字段名和全部字段值。 HLEN 键名
得到该键名的字段数。
========list类型值LPUSH 键名 值1 值2...
从左侧插入数据,RPUSH
表示从右侧插入。返回该键的元素数量。 LPOP 键名
从列表左侧弹出一个元素。RPOP
表示从右侧弹出。LLEN 键名
返回列表中元素的个数。不存在返回0。LRANGE 键名 起始索引 结尾索引
从左往右,获取列表分片,起始从0开始,并且包含两端的元素。索引为负值,如-1表示右边的第一个元素。 LRANGE 键名 0 -1
能够获取列表中全部元素,另外若”起始索引“位置比”结尾索引“位置靠后,会返回空列表;”结尾索引“大于实际索引范围则会返回到列表最右边的元素为止。 LTRIM 键名 起始索引 结尾索引
删除指定索引范围外的全部元素。
LREM 键名 个数 值
当”个数“>0时,会删除从左边数前"个数"个值为"值"的元素; 当”个数“=0时,会删除全部值为"值"的元素;当”个数“<0时,会删除从右边数前"个数"的绝对值个值为"值"的元素。返回实际删除的元素个数。
LINDEX 键名 索引
获取指定索引(从0开始,负数表示从右边开始计算最右是-1)的元素值。LSET 键名 索引 值
设置指定索引的元素值。LINSERT 键名 BEFORE|AFTER pivot value
从左到右找到值为pivot的元素,而后根据第二个参数BEFORE|AFTER将value插入到该值的前或后面。返回最后列表的元素的个数。
RPOPLPUSH source destination
从源列表RPOP一个元素,而后LPUSH到目标列表。返回这个元素的值。至关于一个队列操做。源和目标列表能够是同一个列表。
========set类型值SADD 键名 元素1 元素2...
增添一个或多个元素,键不存在自动建立。返回成功加入元素的个数。SREM 键名 元素1 元素2...
删除一个或多个元素,返回删除成功的个数。 SPOP 键名
从集合中随机弹出一个元素。
SMEMBERS 键名
返回集合中全部元素。SRANDMEMBER 键名
随机从集合中获取一个元素。后面也能够加数字表示返回该数字个元素,分正、负、以及大于集合数的状况。
ps:这种“随机”对每个元素并非平等的。首先是随机选一个桶,而后在桶里随机选元素。没有哈希冲突的元素被选中的概率要大于有哈希冲突的。
SCARD 键名
获取集合中元素个数。SISMEMBER 键名 元素
判断元素是否在集合中。存在返回1,不存在或键不存在时返回0。
SDIFF 键1 键2 键3...
多集合的差集运算。使用SDIFFSTORE 键0 键1 键2 ...
将结果集存储在键0中。SINTER 键1 键2 键3...
多集合的交集运算。SINTERSTORE、SUNIONSTORE
相似。SUNION 键1 键2 键3...
多集合的并集运算。
========sorted set类型值ZADD 键名 score1 元素1 score2 元素2 ...
增长元素,返回新增元素个数(不包括重复覆盖的)。 ZSCORE 键名 元素
获取元素的score。ZRANGE 键名 start stop
返回按score从小到大排序后在指定索引区间里(包含两端) 的元素。加上WITHSCORES
也会返回元素的score。另外从大到小,使用ZREVRANGE
。
ZRANGEBYSCORE 键名 minScore maxScore
返回指定score范围里的元素。也可带WITHSCORES
,以及LIMIT offset count
,还能够指定不包含端点值,还可使用-inf、+inf
表示负无穷、正无穷。一样也有ZREVRANGEBYSCORE
,先maxScore再minScore。
ZINCRBY 键名 increment 元素
增长某个元素的score,返回最后该元素的分数。元素不存在时,会初始化为0再加。
ZCARD、ZCOUNT、ZREM、ZREMRANGEBYRANK、ZREMRANGEBYSCORE、ZRANK
以及一些集合运算命令
redis提供了对列表、集合、有序集合(忽略score)类型键的排序命令SORT
。
能够对数字排序,还有指定ALPHA
参数实现字典排序。 DESC
实现倒序。 LIMIT offset count
实现返回值的指定范围(跳过前offset个元素,获取count个元素)。
BY
参数后面加参考键(字符串类型或hash类型键的某个字段键名->字段名
),命令将对“每一个元素的值替换参考键中第一个(能够是键名带,能够是字段名带*)并获取其值后的值”排序。
若获得的值相同,则会再比较元素自己的值再排序。
当参考键不带*时(常量键名,与元素值无关),或改参考键不存在时,命令不会执行排序操做。
CONFIG SET ...
命令能够在不重启服务的状况下动态修改redis配置,如日志级别loglevel,是否开启持久化等,但也不支持全部的配置项。CONFIG GET ...
命令查看当前配置状况。
redis先将属于一个事务的命令发送给服务器,而后再依次执行这些命令。 MULTI
命令告知服务器接下来的命令都属于同一个事物,后面的命令都会被加入等待执行的事务队列中。EXEC
命令告知服务器将执行事务队列中的全部命令,并保证不会被其余命令插入,当事务里全部命令都执行完后,返回每一个命令的返回值。
redis事务没有回滚功能。若出现执行出错的状况只有本身手动恢复数据。
若出现某条命令须要先获取上一条命令返回值才能继续执行的状况时,因为redis事务中每一个命令的返回值都是最后一块儿返回的,这种状况不能“将上一条命令”与该命令都加入到事务中,而是获取“上一条命令”返回值后再使用事务,并采用相似“锁”的监控机制,在执行事务前防止获取的返回值被改变形成脏读。 WATCH
命令能够监控一个或多个键,一旦其中有一个被改动,以后的事务便不会执行。监控一直持续到EXEC
命令。 也能够用UNWATCH
取消监控
若exec执行失败,再从新执行整个函数。
EXPIRE
设置键的生存时间(Time To Live,TTL),单位秒,必须是整数。PEXPIRE
单位是毫秒。TTL
获取该键还有多久时间被删除,返回-1表示该键已不存在,或没有为该键设置生存时间。PTTL
以毫秒为单位返回剩余时间。 PERSIST
取消生存时间设置。使用SET、GETSET命令为键赋值时也会清除生存时间设置。其余如HSET、ZREM、LPUSH只对键值操做的命令不影响键的生存时间。
若WATCH
监控一个设置了生存时间的键,该键到期天然死亡后,WATCH并不会被认为该键被改变。
到期后的键都会自动被删除吗?
不必定,redis采用的是按期删除+惰性删除策略
。
按期删除
:redis默认每隔100ms检查是否有过时的key,有过时key则删除。但redis不是每一个100ms将全部的key检查一次,而是随机抽取
进行检查(若是每隔100ms,所有key进行检查,redis可能会卡死),所以,若是只采用按期删除策略,会致使不少key到时间没有删除。还须要惰性删除机制
,即在你获取某个key的时候,redis同时也会检查一下,这个key若是设置了过时时间那么是否过时了?若是过时了此时就会删除该键。
每一个键设置多长时间的生存时间?
设置得太长,在内存有限的状况下可能会致使内存占满。
设置过短,可能致使缓存命中率低致使大量内存闲置。
实际开发过程当中会比较难为缓存设置合理的生存时间,通常是经过限制redis最大内存使用量,并让redis按照必定的规则淘汰不须要的缓存键,这样来利用redis缓存系统。
配置文件redis.conf中maxmemory
参数来限制redis最大可用内存(单位字节)。 maxmemory-policy
指定超出内存后的删除规则,直到redis占用内存小于限制内存。有如下几种删除策略:
# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory # is reached. You can select among five behaviors: # # volatile-lru -> remove the key with an expire set using an LRU algorithm # allkeys-lru -> remove any key according to the LRU algorithm # volatile-random -> remove a random key with an expire set # allkeys-random -> remove a random key, any key # volatile-ttl -> remove the key with the nearest expire time (minor TTL) # noeviction -> don't expire at all, just return an error on write operations
1)volatile-lru:即便用LRU算法删除键。当内存不足以容纳新写入数据时,在设置了过时时间的键空间中
,移除最近最少使用的key。这种状况通常是把redis既当缓存,又作持久化存储的时候才用。不推荐。
2)allkeys-lru:也是使用LRU算法删除键。当内存不足以容纳新写入数据时,在键空间中,直接移除最近最少使用的key。推荐使用。
3)volatile-random:当内存不足以容纳新写入数据时,在设置了过时时间的键空间中
,随机移除某个key。依然不推荐。4)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。应该也没人用吧,你不删最少使用Key,去随机删。5)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过时时间的键空间中,有更早过时时间的key优先移除。不推荐。6)noeviction:当内存不足以容纳新写入数据时,新写入操做会报错。(默认的)ps:若是没有设置 expire 的key, 不知足先决条件(prerequisites); 那么 volatile-lru, volatile-random 和 volatile-ttl 策略的行为, 和 noeviction(不删除) 基本上一致。