Products
GG网络技术分享 2025-03-18 16:12 0
文章目录
系统唯一id是我们在设计阶段常常遇到的问题。在复杂的分布式系统中,几乎都需要对大量的数据和消息进行唯一标识。在设计初期,我们需要考虑日后数据量的级别,如果可能会对数据进行分库分表,那么就需要有一个全局唯一id来标识一条数据或记录。生成唯一id的策略有多种,但是每种策略都有它的适用场景、优点以及局限性。
最常见的一种生成id方式。利用数据库本身来进行设置,在全数据库内保持唯一。
【优点】
非常简单。利用现有数据库系统的功能实现,成本小,代码简单,性能可以接受。ID号单调递增。可以实现一些对ID有特殊要求的业务,比如对分页或者排序结果这类需求有帮助。
【缺点】
【部分优化方案】
针对主库单点, 如果有多个Master库,则每个Master库设置的起始数字不一样,步长一样,可以是Master的个数。比如:Master1 生成的是 1,4,7,10,Master2生成的是2,5,8,11 Master3生成的是 3,6,9,12。这样就可以有效生成集群中的唯一ID,也可以大大降低ID生成数据库操作的负载。
常见的生成id方式,利用程序生成。
UUID (Universally Unique Identifier) 的目的,是让分布式系统中的所有元素,都能有唯一的辨识资讯,而不需要透过中央控制端来做辨识资讯的指定。如此一来,每个人都可以建立不与其它人冲突的 UUID。在这样的情况下,就不需考虑数据库建立时的名称重复问题。
UUID的标准形式包含32个16进制数字,以连字号分为五段,形式为8-4-4-4-12的36个字符,示例:550e8400-e29b-41d4-a716-446655440000,到目前为止业界一共有5种方式生成UUID。
在Java中我们可以直接使用下面的API生成UUID:
UUID uuid = UUID.randomUUID(); String s = UUID.randomUUID().toString();
【优点】
【缺点】
【部分优化方案】
当使用数据库来生成ID性能不够要求的时候,我们可以尝试使用Redis来生成ID。这主要依赖于Redis是单线程的,所以也可以用生成全局唯一的ID。可以用Redis的原子操作 INCR和INCRBY来实现。
可以使用Redis集群来获取更高的吞吐量。假如一个集群中有5台Redis。可以初始化每台Redis的值分别是1,2,3,4,5,然后步长都是5。各个Redis生成的ID为:
这个负载到哪台机器上需要提前设定好,未来很难做修改。但是3-5台服务器基本能够满足,都可以获得不同的ID。步长和初始值一定需要事先设定好。使用Redis集群也可以防止单点故障的问题。
比较适合使用Redis来生成日切流水号。比如订单号=日期+当日自增长号。可以每天在Redis中生成一个Key,使用INCR进行累加。
【优点】
【缺点】
zookeeper主要通过其znode数据版本来生成序列号,可以生成32位和64位的数据版本号,客户端可以使用这个版本号来作为唯一的序列号。
很少会使用zookeeper来生成唯一ID。主要是由于需要依赖zookeeper,并且是多步调用API,如果在竞争较大的情况下,需要考虑使用分布式锁。因此,性能在高并发的分布式环境下,也不甚理想。
snowflake(雪花算法)是Twitter开源的分布式ID生成算法,结果是一个long型的ID。这种方案把64-bit分别划分成多段,分开来标示机器、时间等。如图:
其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。具体实现的代码可以参看github。
snowflake算法可以根据自身项目的需要进行一定的修改。比如估算未来的数据中心个数,每个数据中心的机器数以及统一毫秒可以能的并发数来调整在算法中所需要的bit数。
【优点】
【缺点】
我们都知道wordpress默认是把标题作为url的,但中文标题作为url就会很丑,也不利于SEO。中文标题最好的方式就是以文字ID形式作为URL。但是自定义文章类型(custom post type)是不支持在固定连接项设置链接格式的,所以我们必须通过代码来自定义它的固定URL格式。假设我们已创建了book类型的文章,(具体怎么创建自定义文章类型不在本文讨论之列)并且用中文当做文章标题,那么默认产生的链接也将是中文,中文链接通常是编码,比较长,也很丑陋。为了让自定义文章类型的URL变的更简洁,我们就有必要通过rewrite来改写固定连接格式。
目标:将http://www.domain.com/book/harry-potter-book变成http://www.domain.com/book/88.html,也就是用文章的ID作为链接格式。要达到这个目的:创建新的rewrite规则翻译URL,添加filter(post_type_link),当get_the_permalink()函数调用时,返回正确的链接格式。
以下是两种不同的实现方式,都可以实现这个要求,代码需贴到模板文件functions.php中,并且要到后台“固定链接”设置中重新保存固定链接更新.htaccess文件后,url格式才能生效。
1、修改自定义文章类型固定链接格式方法一:
/*
重写自定义文章类型URL规则
代码来源: www.wpzxbj.com
*/
add_action(\'init\', \'custom_book_rewrite\');
function custom_book_rewrite() {
global $wp_rewrite;
$queryarg = \'post_type=book&p=\';
$wp_rewrite->add_rewrite_tag(\'%qid%\', \'([^/]+)\', $queryarg);
$wp_rewrite->add_permastruct(\'book\', \'/book/%qid%.html\', false);
}
add_filter(\'post_type_link\', \'custom_book_permalink\', 1, 3);
function custom_book_permalink($post_link, $post = 0) {
global $wp_rewrite;
if ( $post->post_type == \'book\' ){
$post = &get_post($id);
if ( is_wp_error( $post ) )
return $post;
$newlink = $wp_rewrite->get_extra_permastruct(\'book\');
$newlink = str_replace(\"%qid%\", $post->ID, $newlink);
$newlink = home_url(user_trailingslashit($newlink));
return $newlink;
} else {
return $post_link;
}
}
2、修改自定义文章类型固定链接格式方法二:
/*
重写自定义文章类型URL规则
代码来源: www.wpzxbj.com
*/
add_filter(\'post_type_link\', \'custom_book_link\', 1, 3);
function custom_book_link( $link, $post = 0 ){
if ( $post->post_type == \'book\' ){
return home_url( \'book/\' . $post->ID .\'.html\' );
} else {
return $link;
}
}
add_action( \'init\', \'custom_book_rewrites_init\' );
function custom_book_rewrites_init(){
add_rewrite_rule(
\'book/([0-9]+)?.html$\',
\'index.php?post_type=book&p=$matches[1]\',
\'top\' );
}
3、同时修改多个custom post type自定义文章类型固定链接格式,可用以下代码实现,无需每个自定义文章类型都添加修改固定链接代码:
$mytypes = array(
\'type1\' => \'slug1\',
\'type2\' => \'slug2\',
\'type3\' => \'slug3\'
);
add_filter(\'post_type_link\', \'custom_book_link\', 1, 3);
function custom_book_link( $link, $post = 0 ){
global $mytypes;
if ( in_array( $post->post_type,array_keys($mytypes) ) ){
return home_url( $mytypes[$post->post_type].\'/\' . $post->ID .\'.html\' );
} else {
return $link;
}
}
add_action( \'init\', \'custom_book_rewrites_init\' );
function custom_book_rewrites_init(){
global $mytypes;
foreach( $mytypes as $k => $v ) {
add_rewrite_rule(
$v.\'/([0-9]+)?.html$\',
\'index.php?post_type=\'.$k.\'&p=$matches[1]\',
\'top\' );
}
}
说明:$mytypes数组存储需要更改固定链接的Custom Post Type和它们的固定链接前缀,例如type1这个自定义文章类型的固定链接将是http://www.domain.com/slug1/888.html
Demand feedback