数据库调研:memcached

复制代码

介绍

memcached是高性能多线程的分布式缓存k-v数据库。Memcached是内存中的键值数据库,用于缓存从数据库调用,API调用的任意小块数据(字符串,对象)。可以通过缓存减轻数据库或IO的负载,从而增加应用的性能。

核心特征和原理

  • 分布式

使用一致性hash来进行分布式节点选择,进行数据均衡和负载均衡。

  • 缓存

不持久化。采用LRU(最近最少使用)回收空间。

  • k-v数据库

功能单一的k-v数据库。

分布式架构

支持。

使用环形hash空间,对server节点和key都进行hash(32位元的循环冗余校验(CRC-32)计算键值),并且选择双方hash值最靠近的server节点。解决普通取模造成大量迁移的情况。

通过对物理节点虚拟更多节点,比如‘10.0.0.0-1~10.0.0.1-n’,解决server过少导致不均衡的问题。如下(扩容前)


如下(扩容后)


memcached需要在客户端维护节点列表,并进行业务分发。

缓存策略

  • 使用LRU(最近最少使用)回收空间。

LRU(least recently used)最近最少使用。假设 序列为 4 3 4 2 3 1 4 2物理块有3个 则首轮 4调入内存 4次轮 3调入内存 3 4之后 4调入内存 4 3之后 2调入内存 2 4 3之后 3调入内存 3 2 4之后 1调入内存 1 3 2(因为最少使用的是4,所以丢弃4)之后 4调入内存 4 1 3(原理同上)最后 2调入内存 2 4 1复制代码
  • 支持每个kv对的有效时限。

Kv的存储有效时限可以在客户端设置并作为参数传递给服务端

  • 偷懒替代法。

服务端采用分类chunk定长记录,因此删除记录可以只做个标记,可以通过覆盖来回收并复用空间。

  • 比较优秀的内存管理

相比redis等,应该有更高的内存利用率。

k-v数据库

功能单一的k-v数据库。

基本操作

Add
功能:往内存增加一条新的缓存记录
Delete
功能:从内存删除一条缓存记录
Get
功能:从内存中提取一条缓存记录
Replace
功能:替换内存中的缓存记录
Set
功能:设置或者替换内存中的缓存记录,相当于add + replace的功能。
复制代码

原子操作和事务性策略

支持incr,decr,cas等操作

持久化策略---现状

不支持。宕机会丢失数据

需要配合mysql,mariaDb等进行数据持久化设计。或者memcachedb?性能可能会大大降低。

虽然不能持久化,但是目标单纯,功能单一也有优点,可以避免额外设计带来的问题。比如持久化涉及到io的访问,有时候系统io的阻塞,可能会导致缓存性能受影响。

持久化策略---缓存数据一致性策略

  • 查询策略

先查询cache,miss时查询db,并写入cache。

  • 写入策略

采用writethrough策略。写db成功后,失效cache(写只写db;更新数据先更新db,再失效cache)

1,writethrough。如果配合高性能存储。可以先同步到db,如果成功则让缓存失效。(假设删除缓存不会失败,或极小可能性失败)。如果删除缓存失败(cache miss也算成功,其他不可预期失败算失败),则回退db操作(此间,缓存命中优先从缓存读取数据)。

2,writeback。先写入(删除)缓存,再写入db。在高并发的情况,容易出现数据不一致的场景。比如删除缓存后,写入db成功前,用户发起读请求,会导致读取到旧数据,从而引起数据不一致。

3,readonly。不适用。

  • 其他需要考虑的并发性问题

1,线程1查询cache;线程2写db,并失效cache(非原子,非同步写db),写cache

2,事务性问题:一个事务包含多个db操作,db1操作成功,写cache1成功,写db2操作失败,事务回滚,db2数据回滚,cache1无法回滚,导致脏数据。

3,并发性问题:两个更新操作并发,如更新名字,并且cache中key以名字为关键字,更新一写db成功,写缓存XXXX_name1成功。更新二写db成功,写缓存XXXX_name2成功。导致cache脏数据。(多读少写情况下,考虑乐观锁加version解决-类似CAS,如下图)


性能

待测试。

据称在高速网络下,memcached可以轻松处理每秒200,000个以上的请求。并且消耗更少的内存。

貌似不支持组合请求,或合并批量处理。

从其他找到的一个测试如下:memcached貌似不如redis。另外20k以上的大数据会导致请求数显著下降。


其他

  • 高可用和冗余设计

不支持。宕机后数据会丢失,需要配合其他设计。

  • 并发策略

多线程充分利用多核处理器的优势。

数据通过一致性hash分片存储到不同节点。

  • 其他功能

功能较单一。比如只支持单一的数据结构

  • 可维护性

一般

  • 扩展设计

一致性hash可以保证扩容或故障时,影响较小的数据。

  • 商业成熟度

比较成熟。很流行,被广泛使用。

通过memcached的客户端实现分布式,支持多种语言的客户端,包括c,java等等。

  • 代码量

1.47大概只有1万行左右。代码可读性不如redis。

  • 开源协议

BSD开源协议

  • 依赖

依赖libevent

扩展

原作者开发go的替代版groupcache

https://www.csdn.net/article/2013-07-30/2816399-groupcache-readme-go

优化

内存要足够避免使用swap减低性能,并尽量节点间内存一致。

总结

  • key长度有限制。

存储的key不超过250字节,数据不能超过1M,最好小于10K。因为数据太大容易导致LRU淘汰比较严重,而且Memcached是CPU密集型的程序,容易降低QPS。

  • 支持的数据类型单一

如果需要序列化和反序列化,需要考虑额外开销

  • 不使用场景

写频繁的数据不适合使用缓存。

没有持久化和副本。任意节点掉电(非多台整系统掉电)都会导致数据丢失。对一致性,实时性,安全性要求极高的业务,可能不适合缓存。

  • 多线程开销

在memcached多线程环境下使用CAS,在高并发上高QPS的情况下可能性能会显著降低。

参考资料

http://www.quweiji.com/memcachedb-tokyo-tyrant-redis-performance-test/

http://www.cnblogs.com/hjwublog/p/5625275.html

http://ruturaj.net/redis-memcached-tokyo-tyrant-and-mysql-comparision/

https://stackoverflow.com/questions/2873249/is-memcached-a-dinosaur-in-comparison-to-redis/8494397#8494397


作者:luciham@gmail.com
出处:https://juejin.im/user/5a4e11d96fb9a01c9f5b3367
本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。复制代码


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值