以下内容均来自该网站
http://c.biancheng.net/view/4540.html
1 字符串数据结构
上面是Redis字符串数据结构
43 链表数据结构
一个key对应着一个链表,也就是说这个链表的名字叫做key。然后链表的每一个节点仅有一个值:value
箭头指的分别是链表的名字和链表节点,节点的值就是node1,node2
数据结构是一个的集合,这个集合里面有很多元素。有一个键值key指向这个集合,通过key可以找到这个集合。
事务
在 Redis 中,也存在多个客户端同时向 Redis 系统发送命令的并发可能性,因此同一个数据,可能在不同的时刻被不同的线程所操纵,这样就出现了并发下的数据一致的问题。为了保证异性数据的安全性,Redis 为提供了事务方案。而 Redis 的事务是使用 MULTI-EXEC 的命令组合,使用它可以提供两个重要的保证:
事务是一个被隔离的操作,事务中的方法都会被 Redis 进行序列化并按顺序执行,事务在执行的过程中不会被其他客户端发生的命令所打断。
事务是一个原子性的操作,它要么全部执行,要么就什么都不执行。
这里有一个需要特别注意的地方。命令的错误分成两类。
(1)如果命令的格式没有错误,只是数据结构出现错误,如上图第一个事务的“incr key1“,key1对应的value是string,不能够+1,,那么执行事务的时候,该条命令前面的所有命令和该命令后面所有命令都能顺利执行,该命令不执行。
(2)如果该命令的格式错误,如第二条事务的“incr”,直接少了一个参数,此时整个事务所有命令都不会执行。如上图所示,key1对应的value没有改成v1,仍然是value1.
上图是Redis执行事务的过程
下面是事务的例子1,当客户端1执行watch key1后,在执行事务的过程中,客户端2修改了key1对应的value,这时候会导致客户端1的事务回滚。
下面是事务的第二个例子
客户端1watch key1了,然后客户端在事务中吧key1对应的value改了,这时候是可以的。
Redis的订阅
执行的顺序是红色数字1,2,3
Redis的超时
这里有一个问题需要讨论:如果 key 超时了,Redis 会回收 key 的存储空间吗?这也是面试时常常被问到的一个问题。
答案是不会。这里读者需要非常注意的是:Redis 的 key 超时不会被其自动回收,它只会标识哪些键值对超时了。
这样做的一个好处在于,如果一个很大的键值对超时,比如一个列表或者哈希结构,存在数以百万个元素,要对其回收需要很长的时间。如果采用超时回收,则可能产生停顿。坏处也很明显,这些超时的键值对会浪费比较多的空间。
Redis过期策略
过期策略通常有以下三种:
1.定时过期
每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。
2.惰性过期
只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
3.定期过期
每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。
Redis中同时使用了惰性过期和定期过期两种过期策略。
Redis主从复
Redis 和数据库读操作
数据缓存往往会在 Redis 上设置超时时间,当设置 Redis 的数据超时后,Redis 就没法读出数据了,这个时候就会触发程序读取数据库,然后将读取的数据库数据写入 Redis(此时会给 Redis 重设超时时间),这样程序在读取的过程中就能按一定的时间间隔刷新数据了,读取数据的流程如图 2 所示。